什么是反射?反射与Class类有什么关系?
说起java的核心,或者是框架的核心,肯定很多人都会说反射和注解。那么反射到底是何方神圣,为何从外面看起来那么神秘?
这里就写一些博主自己对反射的理解,就不再对官方描述进行赘述。
从反射这个定义出发,汽车的后视镜就是这个作用,反射后方的车况或者路况。而java中反射的就是一个类的信息,包括类的属性、方法、构造函数。那么就有人说,这个不是自己写的吗?难道还能不知道不成,但是回头一想,如果不确定某个类的信息呢?
Class类的存在就是对反射做的技术支持,或者说在java中通过Class类完成反射这个操作。对于Class类就理解为一个普通的类就好,不应过分纠结于为什么这个类会class这个java中至关重要的东西重名。
Class类基础操作(反射基本操作)
不要过于执着于字面意思,其实说白了就是就是将某个类反射出来,而反射的结果就是Class类,抽象点说Class类就是类的类。
测试准备的Student类(注意其中有非私有属性和私有方法):
public class Student {
private String name;
private int age;
public String job = "study";
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;
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Student() {
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
private void testReflect() {
System.out.println("反射测试");
}
}
1.利用反射创建对象
说是创建对象,其实可以理解为创建某个类对应的Class类,有三种方式
1.1 通过getClass()方法获得Class类
//1.getClass()方法获得
String test = "adad";
Class<? extends String> class1 = test.getClass();
System.out.println(class1);
1.2 通过 类名.class 属性获得Class类
//2.通过 类.class属性获取
Class class2 = String.class;
System.out.println(class2);
1.3 通过Class类静态方法Class.forName()方法获得,参数是类的全路径
//3.通过Class类的静态方法Class.forName(全路径)获得
Class<?> class3 = Class.forName("java.lang.String");
System.out.println(class3);
三种的结果如下图:
2.通过Class类获取类的属性
2.1 通过getFields()获得所有非私有属性
注意还有getField()方法,为了演示方便就全部获取,因此用的是getFields()方法
//首先拿到类的class类,然后调用getFields方法获取
Class c1 = Student.class;
//getFileds获取的是公有属性
Field[] fields = c1.getFields();
for(Field f:fields) {
System.out.println(f);
}
结果如下:
2.2 通过getDeclaredFields()获取所有属性(包括私有的)
同样有getDeclaredField()方法
//getDeclaredFields获取的是所有属性
Field[] declaredFields = c1.getDeclaredFields();
for(Field f:declaredFields) {
System.out.println(f);
}
结果:
3.通过Class类获取类的方法
3.1 通过getMethods()获取所有非私有方法
注意同样有getMethod()方法,获得单一的非私有方法
//获取所有公有方法
Method[] methods = c1.getMethods();
for(Method m:methods) {
System.out.println(m);
}
注意Student中有这个私有方法:
结果如下:
其中还有get/set方法,所以看起来比较多,但是并没有私有方法
3.2通过getDeclaredMethods()获取所有方法(包括私有)
注意同样有getDeclaredMethod()获取单一的方法
//获取所有包括私有方法
Method[] declaredMethods = c1.getDeclaredMethods();
for(Method m:declaredMethods) {
System.out.println(m);
}
结果如下:
4.通过Class类获取构造函数
通过getConstructors()拿到所有构造函数,不论有参还是无参,因为我们模拟的是对Student这个类完全未知,因此要先拿到全部构造函数再做其他操作。
Constructor[] constructors = c1.getConstructors();
for(Constructor<Student> c:constructors) {
System.out.println(c);
}
结果:
5.综合小练习
创建一个Student类的Class类(反射),并且让Student的反射类实例化一个对象
为了模拟完全未知,所以我们先拿到所有构造函数,才能通过getConstructor()方法得到的构造函数进行对象实例化。注意getConstructor()方法中的参数,可以理解为原参数的Class类
5.1 Class类实例化对象的两种方法
第一种:通过 class类调用newInstance()方法
第二种:通过 构造函数.newInstance()方法
如下整个练习代码(包括两种实例化对象的方法)
//实例化class对象
//1.newinstance()方法
Class<Student> c1 = Student.class;
Object stu1 = c1.newInstance();
System.out.println(stu1);
//2.先通过getConstructor拿到构造函数在进行实例化
Constructor[] constructors = c1.getConstructors();
for(Constructor<Student> c:constructors) {
System.out.println(c);
}
System.out.println("-------------");
//注意getConstructor()方法中的参数
Constructor<Student> constructor = c1.getConstructor(String.class,int.class);
Student stu2 = constructor.newInstance("小杨",5);
System.out.println(stu2);
结果: