发生什么事了
反射机制,是在程序运行时动态加载类并获取类的详细信息,从而操作类的属性和方法。
使用反射机制,可以动态的获取当前calss
信息,比如方法信息
,注解信息
还有方法参数
等等。
不讲武德
虽然反射机制很灵活,但是他有一定的资源开销,会一定程度上降低程序的性能.
基础知识
字段解释
- Class 类实体
- Field 类属性变量
- Method 类方法
- Constructor 类构造方法
- getField,getMethod,getConstructor 可以获取指定方法的域,方法和构造器,不包括 private内容
- getDeclated... 可以获取类全部域,方法和构造器,包括 private内容
创建反射的三种方式
- Object.getClass()
Entity entity = new Entity();
Class<? extends Entity> class1 = entity.getClass();
- ClassName.class
Class<Entity> class2 = Entity.class;
- Class.forName()
推荐
Class<?> class3 = Class.forName("reflect.Entity");
Field对象
field对象是反射中的字段对象。
- getName()
获取字段名称
- getType()
获取字段类型
- setAccessible()
设置访问权限
- set(obj,val)
给对象设值
- get(obj)
获取对象值
Method 对象
Method 对象是反射中的方法对象
- getName
获取方法名称
- getReturnType
获取返回值类型
- invoke
用来执行对象方法
构造器操作
调用无参构造-newInstance()
Class<?> aClass = Class.forName("reflect.Entity");
// 调用无参构造函数初始化
Entity entity = (Entity) aClass.newInstance();
entity.sayHello();
你好,null
调用有参构造-getConstructor()
- getConstructor(TypeName.class)
- newInstance()
class Entity {
public String str;
private String name;
public Entity(String name) {
this.name = name;
}
Entity() {
}
public void sayHello() {
System.out.println(String.format("你好,%s", this.name));
}
public void hello() {
System.out.println("hello");
}
public int sum(int a, int b) {
return a + b;
}
}
// 获取有参构造
Constructor<?> constructor = aClass.getConstructor(String.class);
// 调用有参构造
Entity tom = ((Entity) constructor.newInstance("tom"));
tom.sayHello();
你好,tom
字段操作
获取指定公有字段-getField()
Class<?> aClass = Class.forName("reflect.Entity");
Entity entity = (Entity) aClass.newInstance();
Field str = aClass.getField("str");
// set 方法给字段设置值
str.set(entity, "publicStr");
// 输出值
System.out.println(entity.str);
publicStr
获取所有共有字段-getFields()
getFields()方法来获取所有公有字段。
Class<?> aClass = Class.forName("reflect.Entity");
for (Field field : aClass.getFields()) {
System.out.println(field);
}
获取指定私有字段-getDeclaredField()
需要注意的是 私有字段访问需要调用
setAccessible()
方法来指定权限
Class<?> aClass = Class.forName("reflect.Entity");
Entity entity = (Entity) aClass.newInstance();
Field name = aClass.getDeclaredField("name");
// 开启暴力反射 指定访问权限
name.setAccessible(true);
name.set(entity,"jerry");
entity.sayHello();
你好,jerry
获取所私有有字段-getDeclaredFields()
getFields()
只能获取public
属性。
如果要获取private
属性,则需要getDeclaredFields()
方法。
Class<?> aClass = Class.forName("reflect.Entity");
for (Field declaredField : aClass.getDeclaredFields()) {
System.out.println(declaredField);
}
方法调用
获取所有公有方法-getMethods()
Class<?> aClass = Class.forName("reflect.Entity");
for (Method method : aClass.getMethods()) {
System.out.println(method);
}
public void reflect.Entity.sayHello()
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
获取指定公有方法-getMethod()
通过
getMethod()
方法来获取一个方法的Method
对象,然后通过invoke()
来实现方法的调用。
Class<?> aClass = Class.forName("reflect.Entity");
Entity entity = (Entity) aClass.getConstructor(String.class).newInstance("tom");
Method method = aClass.getMethod("sayHello");
// 调用方法
method.invoke(entity);
你好,tom
获取指定公有方法-getMethod()
Class<?> aClass = Class.forName("reflect.Entity");
Entity entity = (Entity) aClass.getConstructor(String.class).newInstance("tom");
Method hello = aClass.getMethod("hello");
hello.invoke(entity);
hello
获取所有私有方法-getDeclaredMethods()
Class<?> aClass = Class.forName("reflect.Entity");
for (Method declaredMethod : aClass.getDeclaredMethods()) {
System.out.println(declaredMethod);
}
public void reflect.Entity.sayHello()
获取指定私有方法-getDeclaredMethod()
Class<?> aClass = Class.forName("reflect.Entity");
Entity entity = (Entity) aClass.getConstructor(String.class).newInstance("tom");
Method sayHello = aClass.getDeclaredMethod("sayHello");
// 设置访问权限
sayHello.setAccessible(true);
sayHello.invoke(entity);
你好,tom
调用有参方法
Class<?> aClass = Class.forName("reflect.Entity");
Entity entity = (Entity) aClass.getConstructor(String.class).newInstance("tom");
// 调用有参方法
int result = ((int) aClass.getMethod("sum", int.class, int.class).invoke(entity,1, 2));
System.out.println(result);
3
黑魔法:通过反射越过泛型检查
原理,泛型检查属于编译期,而反射属于
runtime
所以可以越过泛型检查。
System.out.println("=======");
List<String> list = new ArrayList<>();
Class<? extends List> aClass = list.getClass();
Method add = aClass.getDeclaredMethod("add", Object.class);
add.invoke(list, 1);
add.invoke(list, "1");
add.invoke(list, 1.23);
for (Object s : list) {
System.out.println(s);
}
=======
1
1
1.23