目录
一、概述
二、class类:
1、获取类的字节码文件:
(1)方式一:直接通过一个class的静态变量class获取
(2)方式二:如果知道一个class的完整类名,可以通过静态方法Class.forName()获取
(3)方式三:通过具体对象的getClass方法获取
2、Class.newInstance()通过字节码文件对象创建具体类的实例:(此类中必须有无参构造方法)
3、Class常用的方法:
三、调用构造方法
1、getConstructors() 获取所有被public修饰的构造方法
2、getDeclaredConstructors()获取所有的构造方法(不受访问修饰符限制)
3、getConstructor()获取某个指定的被public修饰的构造方法
4、getDeclaredConstructor 获取指定的某个构造方法 可以给泛型
5、解剖构造方法
(1)getModifiers():获取构造方法的权限修饰符:包访问修饰符-0 public-1 private-2 protected-4
(2)setAccessible(true):临时取消权限校验符
四、获取继承关系:
1、getSuperclass():获取该类继承的类,返回Class对象
2、getlnterfaces():获取该类实现的所有接口,返回Class 型数组
五、访问字段
1、获取成员变量:
(1)getFields()获取所有的被public修饰的成员变量(包含父类的成员变量)
(2)getDeclaredFields()获取所有本类中的成员变量(包含私有的等)
(3)getField()获取本类中或者父类中的某个被public修饰的成员变量
(4)getDeclaredField()获取本类中的某个成员变量
2、解剖成员变量:
(1)getModifiers():获取权限修饰符
(2)getType():获取数据类型
(3)getName():获取变量名
3、应用:
(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-4int 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;}@Overridepublic 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;}@Overridepublic String toString() {return "Dog{" +"name='" + name + '\'' +", type='" + type + '\'' +", weight=" + weight +", height=" + height +", color=" + color +'}';}
}