JAVA入门——反射
一、什么是反射
- 反射允许对封装类的字段、方法和构造函数的信息进行编程访问
- 我们是从class字节码文件中获取这些信息的,所以先学习如何获取class文件
二、获取class对象的三种方式
Class.forName("全类名")
类名.class
对象.getClass()
例:
- 第一种最常用,第二种多当做参数用,第三种只有在有了类对象时会用
public class MyReflectTest1 {
public static void main(String[] args) throws ClassNotFoundException {
//1.第一种方式:
//全类名:包名+类名
Class class1 = Class.forName("com.ma6.reflect.Student");
//2.第二种方式:
Class class2 = Student.class;
//3.第三种方式:
Class class3 = new Student().getClass();
System.out.println(class1 == class2);
System.out.println(class2 == class3);
}
}
三、利用反射获取构造方法(Class类中方法)
Constructor是一个描述构造方法的类,JAVA中的所有事物都能看做对象,都有对应的类
Constructor<?>[] getConstructors(); //返回所有公共构造方法对象的数组
Constructor<?>[] getDeclaredConstructors(); //返回所有构造方法对象的数组
Constructor<T> getConstructor(Class<?>...parameterTypes); //返回单个公共构造方法对象
Constructor<T> getDeclaredConstructor(Class<?>...parameterTypes); //返回单个构造方法对象
注意:
- 使用带有Declared的方法确实能获取私有的构造方法,但这仅仅是能看到,不能使用
- 如果想要使用,需要先调用setAccessiable方法,传递true,再调用构造方法,这种方法称做“暴力反射”
小例子:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class MyReflectTest2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//1.获取字节码文件对象
Class<?> clazz = Class.forName("com.ma6.reflect.Student");
//2.获取构造方法
//<?>是无界通配符,可以匹配任意类型
/* Constructor<?>[] cons = clazz.getConstructors();
for (Constructor<?> con : cons) {
System.out.println(con);
}
System.out.println();*/
/* Constructor<?>[] cons1 = clazz.getDeclaredConstructors();
for (Constructor<?> con : cons1) {
System.out.println(con);
}
System.out.println();*/
/* //获取空参构造
Constructor<?> con2 = clazz.getDeclaredConstructor();
System.out.println(con2);
//获取String的构造
Constructor<?> con3 = clazz.getDeclaredConstructor(String.class);
System.out.println(con3);
//获取int的构造
Constructor<?> con4 = clazz.getConstructor(int.class);
System.out.println(con4);*/
//获取String,int的构造
Constructor<?> con5 = clazz.getConstructor(int.class, String.class);
System.out.println(con5);
//3.获取构造方法属性
//获取权限修饰符,构造方法的所有属性都能查询,详细查询帮助文档
int modifiers = con5.getModifiers();
System.out.println(modifiers);
//4.可以用来创建对象
Student stu = (Student)con5.newInstance(11, "王牛牛牛");
System.out.println(stu);
}
}
四、利用反射获取成员变量
Field:描述成员变量类
Field[] getFields(); //返回所有公共成员变量对象的数组
Field[] getDeclaredFields();//返回所有成员变量对象的数组
Field getField(String name);//返回单个公共成员变量对象
Field getDeclaredField(String name);//返回单个成员变量对象
Field类中用于创建对象的方法:
void set(Object obj,Object value);//赋值
Object get(Object obj); //获取值
import java.lang.reflect.Field;
public class MyReflectTest3 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Class<?> clazz = Class.forName("com.ma6.reflect.Student");
//1.
Field[] field = clazz.getDeclaredFields();
for (Field field1 : field) {
System.out.println(field1);
}
//2.
Field name = clazz.getDeclaredField("name");
System.out.println(name);
//3.
String n = name.getName();
int mod = name.getModifiers();
Class<?> type = name.getType();
//4.获取成员变量记录的值
Student s = new Student(13,"王牛牛牛");
name.setAccessible(true);//私有变量,要暴力反射
String value = (String)name.get(s);
System.out.println(value);
//5.修改对象里的值
name.set(s,"王犇");
System.out.println(s);
}
}
五、反射获取成员方法
Method:描述成员方法的类
Method[] getMethods(); //返回所有公共成员方法,包括继承
Method[] getDeclaredMethods();//返回所有成员方法对象,不包括继承
Method getMethods(String name,Class<?>...parameterTypes);
Method getDeclaredMethods(String name,Class<?>...parameterTypes);
Method类中创建对象方法:(方法运行)
Object invoke(Object obj,Object...args)
用obj调用方法,args是传的参数
public class MyReflectTest4 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//1.
Class<?> clazz = Class.forName("com.ma6.reflect.Student");
//2.
Method eat = clazz.getDeclaredMethod("eat", String.class);
System.out.println(eat);
//3.
Student s = new Student();
eat.setAccessible(true);
eat.invoke(s,"史");
}
}