反射是指在java程序运行过程中可以获取任意一个类的属性和方法,可以调用任意对象的属性和方法,这就是java反射机制。
一、获取Class的方法:
1、Class.forName(“类的全限定名称”)
2、类.class
3、对象.getClass()
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public User( ) {
}
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 "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public static void main(String[] args) throws Exception {
//获取class对象的三种方法:
//(1)类.class
Class<User> clazz1 = User.class;
//(2)Class.forName(“类的全限定名称”)
Class<?> clazz2 = Class.forName("com.java基础知识.User");
//(3)通过对象的getClass()方法
User user = new User();
Class<?> clazz3 = user.getClass();
}
二、通过反射来生成对象的两种方法:
1、直接调用newInstance方法,只能调用无参构造器初始化对象;
//(1)调用默认的无参构造函数
User user1 = (User) clazz3.newInstance();
2、先获取构造函数,然后通过构造函数来实例化对象;
先获取指定Class,然后获取其构造函数,然后通过构造器创建具体的对象。
public static void main(String[] args) throws IllegalAccessException, InstantiationException {
// 获取指定的Class
Class c = String.class;
//获取所有的"public"构造函数
Constructor[] constructors = c.getConstructors();
for (int i = 0; i < constructors.length; i++) {
System.out.println("=====" + constructors[i]);
}
//获取所有类型的构造函数
Constructor[] constructors1 = c.getDeclaredConstructors();
for (int i = 0; i < constructors1.length; i++) {
System.out.println(constructors1[i]);
}
}
在getConstructors方法中传入参数类型,即可获取指定参数类型的构造函数。
//获取指定参数类型的构造函数
Constructor constructor2 = c.getConstructor(StringBuilder.class);
//根据指定的构造函数创建对象
String str = (String)constructor2.newInstance(new StringBuilder());
三、获取成员方法并调用
//通过反射获取方法并进行调用
Method toString = clazz3.getMethod("toString");
System.out.println(toString.invoke(user2));
四、获取属性并且给属性赋值
//获取属性,并且给属性赋值
Field age = clazz3.getDeclaredField("age");
//给私有属性赋值,需要修改权限
age.setAccessible(true);
age.set(user2,345);
System.out.println(user2.toString());
五、常用方法
//常用方法,有Declared可以获取私有类型的,不带Declared,只能获取public类型的
//获取注释类型
clazz3.getDeclaredAnnotation(Deprecated.class);
//获取构造函数
clazz3.getDeclaredConstructor(String.class);
//获取方法
clazz3.getDeclaredMethods();
//获取属性
clazz3.getDeclaredFields();
六、其他用法
1、通过将类名和一些初始化参数写在配置文件里面,我们可以做到只修改配置文件,不用修改代码,就可以修改实现的类。
2、因为反射是运行过程中获取或者调用类的属性和方法,所以可以跳过泛型检查这个步骤(编译之后,泛型就被擦除了),这样同时也提高了代码报错的风险。
总结
反射是类加载的反向过程。
类加载的过程:当我们初始化一个类时,jvm会去硬盘上查找.class文件,并加载到jvm内存中,在堆内存中创建一个对象。
反射就是:知道一个对象,反过来去获取的它的各种信息。