(一)什么是反射?
在详细了解反射机制之前,我们先来了解一下java代码在计算机中的运行过程:
比如当我们编写好一个类:Student.java,里面包含学生的姓名和年龄,构造方法,其他方法。
javac会把我们写的代码编译成.class字节码文件,保存在硬盘中,这个文件中保存着该类的类名,成员名,构造方法等等。
Class阶段会把字节码文件中的信息转化成class类对象,比如成员变量用Field[]保存,构造方法用Constructor[]保存,成员方法用Method[]保存
通过new Student(),根据第二个阶段的类对象创建出Student对象
这里的第二个阶段,将类的各个组成部分封装为其他对象就是反射机制。
扫描二维码关注公众号,回复:
8937267 查看本文章
(二)获取字节码Class对象的三种方式
class.forname("全类名");
类名.class;
对象.getclass();
同一个字节码文件(.class)在一次程序运行过程中只会被加载一次,通过以上三种方法创建的class对象是同一个。
public class Student {
private String name;
private int age;
//方便后期测试的成员变量
public int a;
public Student(){}
public Student(String name, int age,int a) {
this.name = name;
this.age = age;
this.a=a;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", a=" + a +
'}';
}
}
public class reflectTest {
public static void main(String[] args) throws ClassNotFoundException {
//方法一
Class cls1 = Class.forName("com.sdxb.reflect.Student");
System.out.println(cls1);
//方法二
Class cls2 = Student.class;
System.out.println(cls2);
//方法三
Student student=new Student();
Class cls3 = student.getClass();
System.out.println(cls3);
//判断是否是同一对象
System.out.println(cls1==cls2);
System.out.println(cls1==cls3);
}
}
(三)Class获取对象方法
1.1 获取成员变量
Field getField(String name) //获取指定名称public修饰的成员变量
Field[] getFields() //获取所有public修饰的成员变量
Field getDeclaredField(String name) //获取指定名称成员变量
Field[] getDeclaredFields() //获取所有成员变量
1.2 操作成员变量
Object get(Object obj) //通过Field获取对象
void set(Object obj, Object value) //修改Field的值
public class FieldTest {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Class cls = Class.forName("com.sdxb.reflect.Student");
//1.获取所有public的成员变量
Field[] fields = cls.getFields();
for (Field field:fields) {
System.out.println(field);
}
//2.获取指定名字的public成员变量
Field a = cls.getField("a");
Student student=new Student();
//3.操作Field的方法,get和set
System.out.println(a.get(student));
a.set(student,10);
System.out.println(student);
//4.获取所有成员变量
Field[] declaredFields = cls.getDeclaredFields();
for (Field f : declaredFields) {
System.out.println(f);
}
}
}
这里的两个操作Field的方法只能操作public修饰的变量,如果需要访问其他修饰符修饰的元素,则要添加安全许可:
a.setAccessible(true);
2.1 获取构造方法
Constructor<T> getConstructor(Class<?>... parameterTypes) //根据参数不同获取指定的public构造方法
Constructor<?>[] getConstructors() //获取所有public构造方法
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) //根据参数不同获取指定的构造方法
Constructor<?>[] getDeclaredConstructors() //获取所有构造方法
2.2 操作构造方法
T newInstance(Object... initargs) //创建对象
public class reflectTest2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class cls = Class.forName("com.sdxb.reflect.Student");
//有参构造方法
Constructor constructor = cls.getConstructor(String.class, int.class, int.class);
Object student = constructor.newInstance("sdxb", 24, 1);
System.out.println(student);
//无参构造方法
Constructor constructor2 = cls.getConstructor();
Object student2 = constructor2.newInstance();
System.out.println(student2);
//无参构造方法可以用下面的方式代替
cls.newInstance();
}
}
Method getMethod(String name, Class<?>... parameterTypes) //根据名称和参数类型获取public方法
Method[] getMethods() //获取所有public方法
Method getDeclaredMethod(String name, Class<?>... parameterTypes) //根据名称和参数类型获取方法
Method[] getDeclaredMethods() //获取所有方法
3.2 成员方法的操作
Object invoke(Object obj, Object... args) //执行成员方法
public void run(){
System.out.println("run");
}
public void run(int speed){
System.out.println("run"+speed);
}
public class reflectTest3 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class cls = Student.class;
Student student=new Student();
//无参方法
Method run = cls.getMethod("run");
run.invoke(student);
//带参数方法
Method run2=cls.getMethod("run", int.class);
run.invoke(student,1);
}
}
(四)总结
java的反射机制在框架中应用十分广泛,被誉为是框架的灵魂。原因是框架是一个半成品,我们无法通过new去创建框架中定义的类,因此反射起到了很大的作用。