先创建一个实体类ReflectTest02
反射是在面试中经常被问到的一个知识点,经常被问到的比如:反射的基本概念,反射一些api,Java中哪些地方使用到了反射或者反射的应用场景等等。
我们在ReflectTest02中设置一些封装的属性、方法,以及一些公共的属性和方法,以便于我们待会测试。
package com.main.Package1;
public class ReflectTest02 {
private int id ;
private String name ;
private int age ;
public String addr;
private ReflectTest02() {
}
public ReflectTest02(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
private void my(String name , String code){
System.out.println("我是私有方法```" + name + " , 代号" + code);
}
@Override
public String toString() {
return "ReflectTest02{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
另写一个类测试反射。
package com.main;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 反射demo
* 1、反射机制的作用
* 通过java语言中的反射机制可以操作字节码文件(可以读和修改字节码文件)
* 通过反射机制可以操作代码片段(.class文件)
* 2、反射机制的相关类在哪个包下?
* java.lang.reflect.*
* 3、反射机制相关的重要的类有哪些?
* java.lang.Class 代表整个字节码,代表一个类型,代表一个类
* java.lang.reflect.Method 代表字节码中的方法字节码,代表类中的方法
* java.lang.reflect.Constructor 代表字节码中的构造方法字节码,代表类中的构造方法
* java.lang.reflect.Field 代表字节码中的属性字节码,代表类中的成员变量(静态变量+实例变量)
*
*/
public class ReflectionTest {
public static void main(String[] args) throws Exception {
// 4、获取Class的三种方式, 三种方式的返回值都是Class类型
// 4.1 Class.forName("完整类名带包名")
Class clazz = Class.forName("com.main.Package1.ReflectTest02");
// 通过newInstance()这个方法调用无参构造方法,来完成对象的创建
// 调用newInstance()这个方法调用的是无参构造,所以必须保证无参构造是存在的
Object obj = clazz.newInstance();
System.out.println(obj); // 结果:com.main.Package1.ReflectTest02@1b6d3586
// 返回完整类名带包名
String name = clazz.getName();
System.out.println(name); // 结果:com.main.Package1.ReflectTest02
// 返回类名
String simpleName = clazz.getSimpleName();
System.out.println(simpleName); // 结果:ReflectTest02
// 返回类中public修饰的属性
Field[] fields = clazz.getFields();
for (Field f : fields) {
System.out.println(f); // 结果:public java.lang.String com.main.Package1.ReflectTest02.addr
}
// 返回类中所有属性 包括私有
Field[] declaredFields = clazz.getDeclaredFields();
for (Field f : declaredFields) {
System.out.println(f);
//结果:
// private int com.main.Package1.ReflectTest02.id
// private java.lang.String com.main.Package1.ReflectTest02.name
// private int com.main.Package1.ReflectTest02.age
// public java.lang.String com.main.Package1.ReflectTest02.addr
}
// 根据属性名name获取指定的属性
Field id = clazz.getDeclaredField("id");
// 注意:set() 不能访问私有属性 需要打破封装才可以 setAccessible() 默认为false 修改为true即可
id.setAccessible(true);
// 给对象属性赋值
id.set(obj , 1);
System.out.println(id.get(obj)); // 结果:1
System.out.println(id); // 结果:private int com.main.Package1.ReflectTest02.id
// 返回类中的所有的实例方法
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method m : declaredMethods) {
System.out.println(m);
}
// 调用私有方法
Method my = clazz.getDeclaredMethod("my" , String.class , String.class);
// 需要注意的是 私有方法默认也是不支持直接访问的 在这里也需要打破封装
my.setAccessible(true);
// 使用 invoke() 方法执行
Object resValue = my.invoke(obj, "周星驰", "007");
// 通过反射调用构造方法实例化对象(含参数)
Constructor constructor1 = clazz.getDeclaredConstructor(int.class, String.class, int.class);
constructor1.setAccessible(true);
Object object1 = constructor1.newInstance(1, "周星驰", 18);
System.out.println(object1);
// 通过反射调用构造方法实例化对象(不含参数)
Constructor constructor2 = clazz.getDeclaredConstructor();
Object object2 = constructor2.newInstance();
System.out.println(object2);
System.out.println("----------------------------" + "获取一个类的父类以及实现的接口" + "----------------------------" );
// 以String为例 我们获取它的父类 和 实现的结构
// 第一步 获取String的class对象
Class string = Class.forName("java.lang.String");
// 获取String的父类 调用 getSuperClass()
Class superclass = string.getSuperclass();
System.out.println(superclass.getName());
// 获取String类实现的所有接口
Class[] interfaces = string.getInterfaces();
for (Class i : interfaces) {
System.out.println(i.getName());
}
// 4.2 对象.getClass()
// 4.3 任何类型.class
}
}