目录
(1)方式一:直接通过一个class的静态变量class获取
(2)方式二:如果知道一个class的完整类名,可以通过静态方法Class.forName()获取
2、Class.newInstance()通过字节码文件对象创建具体类的实例:(此类中必须有无参构造方法)
1、getConstructors() 获取所有被public修饰的构造方法
2、getDeclaredConstructors()获取所有的构造方法(不受访问修饰符限制)
3、getConstructor()获取某个指定的被public修饰的构造方法
4、getDeclaredConstructor 获取指定的某个构造方法 可以给泛型
(1)getModifiers():获取构造方法的权限修饰符:包访问修饰符-0 public-1 private-2 protected-4
(2)setAccessible(true):临时取消权限校验符
1、getSuperclass():获取该类继承的类,返回Class对象
2、getlnterfaces():获取该类实现的所有接口,返回Class 型数组
(1)getFields()获取所有的被public修饰的成员变量(包含父类的成员变量)
(2)getDeclaredFields()获取所有本类中的成员变量(包含私有的等)
(3)getField()获取本类中或者父类中的某个被public修饰的成员变量
(4)getDeclaredField()获取本类中的某个成员变量
(1)get(Object o):获取对象中此成员变量的值:
(2)set(Object o, Object Value)设置对象中此成员变量的值
(3)注意事项:静态成员变量不依赖于对象,静态成员变量共享一片空间,所以可以不传入对象,直接修改修改
一、概述
Java
反射机制是 Java
语言的一个重要特性。在学习 Java
反射机制前,大家应该先了解两个概念:编译期和运行期。
编译期:是指把源码交给编译器编译成计算机可以执行的文件的过程。在 Java
中也就是把 Java
代码编成 class
文件的过程。编译期只是做了一些翻译功能,并没有把代码放在内存中运行起来,而只是把代码当成文本进行操作。比如:检查语法错误。
运行期:是把编译后的文件交给计算机执行,直到程序运行结束。所谓运行期就把在磁盘中的代码放到内存中执行起来。
Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为 Java
语言的反射机制。简单来说,反射机制指的是程序在运行时能够获取自身的信息。在 Java
中,只要给定类的名字,就可以通过反射机制来获得类的所有信息。
Java
反射机制在服务器程序和中间件程序中得到了广泛运用。在服务器端,往往需要根据客户的请求,动态调用某一个对象的特定方法或者为属性赋值。例如:在主流的 ORM
框架的实现中,运用 Java
反射机制可以读取任意一个 JavaBean
的所有属性,或者给这些属性赋值。
Java
反射机制主要提供了以下功能,这些功能都位于java.lang.reflect
包。
- 在运行时判断任意一个对象所属的类。
- 在运行时构造任意一个类的对象。
- 在运行时判断任意一个类所具有的成员变量和方法。
- 在运行时调用任意一个对象的方法。
- 生成动态代理。
二、class类:
要想知道一个类的属性和方法,必须先获取到该类的字节码文件对象。获取类的信息时,使用的就是 Class
类中的方法。所以先要获取到每一个字节码文件(.class
)对应的 Class
类型的对象.class
(包括interface
)的本质是数据类型(Type
)。class
是由JVM
在执行过程中动态加载的。JVM
在第一次读取到一种class
类型时,将其加载进内存。每加载一种class
,JVM
就为其创建一个Class
类型的实例,并关联起来。
注意:这里的Class
类型是一个名叫Class
的class。
1、获取类的字节码文件:
(1)方式一:直接通过一个class的静态变量class获取
//方式一:直接通过一个class的静态变量class获取
Class clazz1=Person.class;
System.out.println(clazz1);
(2)方式二:如果知道一个class的完整类名,可以通过静态方法Class.forName()获取
//方式二:如果知道一个class的完整类名,可以通过静态方法Class.forName()获取
Class clazz2=Class.forName("com.yuan.reflection.Person");
System.out.println(clazz2);
(3)方式三:通过具体对象的getClass方法获取
//方式三:通过具体对象的getClass方法获取
Person p1=new Person();
Class clazz3=p1.getClass();
System.out.println(clazz3);
2、Class.newInstance()通过字节码文件对象创建具体类的实例:(此类中必须有无参构造方法)
//通过Class.newInstance()可以创建类的实例,要求实例必须要有公共的无参构造方法,否则报错
Object p2 = clazz1.newInstance();
System.out.println(p2);
3、Class常用的方法:
类型 | 访问方法 | 返回值类型 | 说明 |
包路径 | getPackage() | Package 对象 | 获取该类的存放路径 |
类名称 | getName() | String 对象 | 获取该类的名称 |
继承类 | getSuperclass() | Class 对象 | 获取该类继承的类 |
实现接口 | getlnterfaces() | Class 型数组 | 获取该类实现的所有接口 |
构造方法 | getConstructors() | Constructor 型数组 | 获取所有权限为 public 的构造方法 |
getDeclaredContruectors() | Constructor 对象 | 获取当前对象的所有构造方法 | |
方法 | getMethods() | Methods 型数组 | 获取所有权限为 public 的方法 |
getDeclaredMethods() | Methods 对象 | 获取当前对象的所有方法 | |
成员变量 | getFields() | Field 型数组 | 获取所有权限为 public 的成员变量 |
getDeclareFileds() | Field 对象 | 获取当前对象的所有成员变量 |
三、调用构造方法
1、getConstructors() 获取所有被public修饰的构造方法
2、getDeclaredConstructors()获取所有的构造方法(不受访问修饰符限制)
3、getConstructor()获取某个指定的被public修饰的构造方法
4、getDeclaredConstructor 获取指定的某个构造方法 可以给泛型
5、解剖构造方法
(1)getModifiers():获取构造方法的权限修饰符:包访问修饰符-0 public-1 private-2 protected-4
(2)setAccessible(true):临时取消权限校验符
public class Demo04 {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//1、获取类的字节码文件对象
Class<Person> clazz = Person.class;
//2、获取构造方法
//getConstructors() 获取所有被public修饰的构造方法
// Constructor[] cons = clazz.getConstructors();
// for (Constructor con:cons) {
// System.out.println(con);
// }
//getDeclaredConstructors()获取所有的构造方法(不受访问修饰符限制)
Constructor[] cons = clazz.getDeclaredConstructors();
for (Constructor con:cons) {
System.out.println(con);
}
//getConstructor()获取某个指定的被public修饰的构造方法
Constructor con = clazz.getConstructor();
System.out.println(con);
//getDeclaredConstructor 获取指定的某个构造方法 可以给泛型
Constructor<Person> con1=clazz.getDeclaredConstructor(String.class,int.class);
System.out.println(con1);
//3、解剖
//包-0 public-1 private-2 protected-4
int modifier = con1.getModifiers();
System.out.println(modifier);
System.out.println("权限修饰符是否是公共的"+Modifier.isPublic(modifier));
Parameter[] parameters = con1.getParameters();
for (Parameter p:parameters) {
System.out.println(p.getType()+"_"+p.getName());
}
//4、实例化对象
con1.setAccessible(true);//临时取消权限校验符
Person p1 = con1.newInstance("张三", 13);//注意构造方法要为public,不是公共的需要设置取消临时校验符
System.out.println(p1);
}
}
四、获取继承关系:
1、getSuperclass():获取该类继承的类,返回Class对象
2、getlnterfaces():获取该类实现的所有接口,返回Class 型数组
public class Demo03 {
public static void main(String[] args) {
Class clazz = Person.class;
//包路径 getPackage() Package对象获取该类的存放路径
Package pac = clazz.getPackage();
System.out.println(pac);
//类名称 getName() String对象 获取该类的名称
String strName = clazz.getName();
System.out.println(strName);
//继承类getSuperclass() Class对象 获取该类继承的类
Class supclasss = clazz.getSuperclass();
System.out.println(supclasss);
//实现的接口
Class[] cles = clazz.getInterfaces();
System.out.println(Arrays.toString(cles));
}
}
五、访问字段
1、获取成员变量:
(1)getFields()获取所有的被public修饰的成员变量(包含父类的成员变量)
(2)getDeclaredFields()获取所有本类中的成员变量(包含私有的等)
(3)getField()获取本类中或者父类中的某个被public修饰的成员变量
(4)getDeclaredField()获取本类中的某个成员变量
Class<Dog> clazz = Dog.class;
//2、获取成员变量
// //getFields()获取所有的被public修饰的成员变量(包含父类的成员变量)
Field[] fields = clazz.getFields();
for (Field f:fields) {
System.out.println(f);
}
//getDeclaredFields()获取所有本类中的成员变量(包含私有的等)
Field[] fields2 = clazz.getDeclaredFields();
for (Field f:fields2) {
System.out.println(f);
}
//getField()获取本类中或者父类中的某个被public修饰的成员变量
Field field = clazz.getField("type");
System.out.println(field);
//getDeclaredField()获取本类中的某个成员变量
Field field = clazz.getDeclaredField("color");
System.out.println(field);
2、解剖成员变量:
(1)getModifiers():获取权限修饰符
(2)getType():获取数据类型
(3)getName():获取变量名
//获取权限修饰符
int modifier = field.getModifiers();
System.out.println("权限修饰符为:"+modifier);
//获取数据类型
Class typeClass = field.getType();
System.out.println("数据类型为:"+typeClass);
//获取变量名
String name = field.getName();
System.out.println("此成员变量的变量名为:"+name);
3、应用:
(1)get(Object o):获取对象中此成员变量的值:
(2)set(Object o, Object Value)设置对象中此成员变量的值
(3)注意事项:静态成员变量不依赖于对象,静态成员变量共享一片空间,所以可以不传入对象,直接修改修改
Dog d2=new Dog();
Dog d1=new Dog("花花",5,"田园犬",20.0,25,"花色");
// field.setAccessible(true);//临时取消校验符
// //获取d1对象中此成员变量的值
// Object obj = field.get(d1);
// System.out.println("获取到成员变量type对应对象d1的值"+obj);
// //设置对象d1中此成员变量的值为黑白
// field.set(d1,"黑白");
// System.out.println(d1);
//静态成员变量不依赖于对象
field.setAccessible(true);//临时取消校验符
//获取静态成员变量,不依赖于对象二存在,所以获取此成员变量的值时,可以不传对象
Object obj = field.get(null);
System.out.println("获取到成员变量type对应对象d1的值"+obj);
//设置成员变量值,静态成员变量共享一片空间,所以可以修改
field.set(null,"黑白");
System.out.println(d1);
System.out.println(d2);
public class Animal {
public String name;
private int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.yuan.reflection;
public class Dog extends Animal{
public String type;
protected double weight;
int height;
public static String color;
public Dog() {
super("小白",23);
}
public Dog(String name, int age, String type, double weight, int height, String color) {
super(name, age);
this.type=type;
this.weight=weight;
this.height=height;
this.color=color;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", type='" + type + '\'' +
", weight=" + weight +
", height=" + height +
", color=" + color +
'}';
}
}