原理:反射首先是能够获取到Java中的反射类的字节码,然后将字节码中的方法,变量,构造函数等映射成 相应的 Method、Filed、Constructor 等类
应用:取出类的modifiers,数据成员,方法,构造器,和超类
找出某个接口里定义的常量和方法说明.
取得和设定对象数据成员的值,如果数据成员名是运行时刻确定的也能做到.
在运行时刻调用动态对象的方法.
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实
现对这个类进行初始化。
- 加载 就是指将 class 文件读入内存,并为之创建一个 Class 对象。 任何类被使用时系统都会建立一个 Class 对象
- 连接 验证 是否有正确的内部结构,并和其他类协调一致 准备 负责为类的静态成员分配内存,并设置默认初始化值 解析 将类的二进制数据中的符号引用替换为直接引用
- 初始化
- 创建类的实例
- 类的静态变量,或者为静态变量赋值
- 类的静态方法
- 使用反射方式来强制创建某个类或接口对应的 java.lang.Class 对象
- 初始化某个类的子类
Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称 为 java 语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖这个类,使用的就是 Class 类中的方法,所以先要获取到每一个字节码文件所对应的 Class 类型对象。
需要掌握 6 个单词
public class A {
/**
* class获得方式
*
* @param args
*/
public static void main(String[] args) {
//1 通过类型获得
// 语法:类名.class
// 应用场景:确定类型 等
Class clazz1 = BrandController.class;
System.out.println("语法:类名.class|" + clazz1);
//2 通过实例对象获得
// 语法:变量.getClass()
// 应用场景:在方法内部通过参数获得类型 等
BrandController brandController = new BrandController();
Class<? extends BrandController> aClass = brandController.getClass();
System.out.println("语法:变量.getClass()|" + aClass);
//3 通过字符串获得
// 语法:Class.forName("全限定类名")
// 应用场景:通过配置获得字符串 等
try {
Class<?> aClass1 = Class.forName("com.controller.BrandController");
System.out.println("Class.forName(\"全限定类名\")|"+aClass1);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
//1 获得 Class
Class clazz = User.class;
// 得到这个类的名字:全限定类名
String name = clazz.getName();
// 这个只是类的名字
String simpleName = clazz.getSimpleName();
System.out.println(" 这个只是类的名字simpleName:"+simpleName);
System.out.println("得到这个类的名字:全限定类名name:"+name);
public class A {
/**
* 构造方法与实例
*
* @param args
*/
public static void main(String[] args) {
//无参构造 , 并实例化
//1 获得 Class
Class<SpecificationOption> specificationOptionClass = SpecificationOption.class;
System.out.println("获得 Class"+specificationOptionClass);
//2 获得构造 -- 没有形参
Constructor<SpecificationOption> constructor = null;
try {
constructor = specificationOptionClass.getConstructor();
System.out.println("获得构造 -- 没有形参"+constructor);
SpecificationOption specificationOption = constructor.newInstance();
System.out.println("实例对象,没有实参"+specificationOption);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class A {
/**
* 构造方法与实例
*
* @param args
*/
public static void main(String[] args) {
//无参构造 , 并实例化
//1 获得 Class
try {
// 获得无参的简化版
SpecificationOption specificationOption = SpecificationOption.class.newInstance();
System.out.println(specificationOption);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
//有参构造 , 并实例化
//1 获得 Class
Class beanClass = SpecificationOption.class;
//2 获得构造 -- 三个字符串形参 -- (Integer.class,String.class,Integer.class)
Constructor constructor = null;
try {
constructor = beanClass.getConstructor(Integer.class, String.class, Integer.class);
System.out.println("获得构造 -- 三个字符串形参" + constructor);
//3 实例对象,三个字符串实参
Object o = constructor.newInstance(2323,"白色", 1);
System.out.println(o);
} catch (Exception e) {
e.printStackTrace();
}
}
private Bean(String id) {
this.id = id;
System.out.println("有参构造:" + id);
}
@Test
public void testPrivateCons() throws Exception{
//私有构造
//1 获得 Class
Class beanClass = Bean.class;
//2 获得构造 -- 两个字符串形参 -- Bean(String id, String className)
// * getConstructor() 将抛异常 java.lang.NoSuchMethodException
// * getDeclaredConstructor 可以获得私有构造
Constructor constructor = beanClass.getDeclaredConstructor(String.class)
//暴力访问
constructor.setAccessible(true);
//3 实例对象,两个字符串实参
Object bean = constructor.newInstance("userId");
System.out.println(bean);
//1 获得 Class
Class clazz = User.class;
//2 获得实例 ,相当于 Object obj = new Bean();
Object obj = clazz.newInstance();
//3 操作 setAge 方法
// * 格式:getMethod(方法名,形成列表)
Method setMethod = clazz.getMethod("setAge", Integer.class);
System.out.println("getMethod(方法名,形成列表)"+setMethod);
//3.2 执行方法,一个实参
Object setReturnObj = setMethod.invoke(obj, 12);
System.out.println("set 方法返回值:" + setReturnObj);
//4 操作 getId 方法
// 4.1 获得方法,没有形参
Method getMethod = clazz.getMethod("getAge");
// 4.2 执行方法,没有实参
Object getReturnObj = getMethod.invoke(obj);
System.out.println("get 方法返回值:" + getReturnObj);
//5 暴力反射私有的构造方法
Method showMethod = clazz.getDeclaredMethod("show");
System.out.println("暴力反射私有的构造方法show "+showMethod);
//暴力访问
showMethod.setAccessible(true);
// 4 执行方法,没有实参
// obj.setMethod(args) user.setAge(20)
Object invoke = setMethod.invoke(obj, 20);
Object result = showMethod.invoke(obj);
System.out.println("show私有"+result);
//有参构造 , 并实例化
Class<User> clazz = User.class;
//2 获得方法 -- main 静态方法 -- public static void main(String[] args)
Method mainMethod = clazz.getMethod("main", String[].class);
Object getReturnObj = mainMethod.invoke(null, (Object)new String[]{"aaa","bbb"});
System.out.println("main 方法返回值:|||||||||" + getReturnObj);
//5 操作字段,进行赋值,public String name;
//5.1 获得的字段,一个形参
// * 格式:getField(字段名)
Field descriptionField = clazz.getField("name");
System.out.println("getField(字段名) "+descriptionField);
//5.2 为对象的字段赋值
descriptionField.set(obj, "喜欢在文字中倾诉");
//5.3 获取对象的字段值
Object fieldReturnObj = descriptionField.get(obj);
System.out.println("description 字段返回值: "+fieldReturnObj);
//5 操作字段,进行赋值,private String name;
//5.1 获得的字段,一个形参
// * 格式:getDeclaredField(字段名)
Field descriptionField = clazz.getDeclaredField("name");
System.out.println("getDeclaredField(字段名) "+descriptionField);
//暴力访问
descriptionField.setAccessible(true);
//5.2 为对象的字段赋值
descriptionField.set(obj, "喜欢在文字中倾诉");
//5.3 获取对象的字段值
Object fieldReturnObj = descriptionField.get(obj);
System.out.println("description 字段返回值: "+fieldReturnObj);