Java 反射

Java 反射

  • 类加载器
  • 反射
  • 动态代理

what:在运行时加载某个类,获得某个类的相关信息,以及进行操作。

类加载器

what:用于将节字码文件加载到JVM

  • 启动类加载器:bootstrap,c++编写,jvm自带,负责加载rt.jar(runtime),无法直接获取,它是所有类加载器的父加载器
  • 扩展类加载器:extension ,jdk_home/lib/ext目录下的jar包或者 -D java.ext.dirs指定目录下的jar包装入工作库
  • System ClassLoader :负责java -classpath或者-D java.class.path所指目录 下的类和jar包装入

委托、可见性以及单一性原理

委托:即子加载器会请求父加载器是否加载,并且加载,如果不能加载就交会子加载器,即自下而上请求,自上而下加载.

可见性: 子类加载器可以看到父类加载器加载的类,而反之则不行

单一性: 父加载器加载过的类不能被子加载器加载第二次

反射

what:运行时获得类信息,注意是运行时。

Class:字节码在jvm存在形式即为Class的对象,是由jvm创建的。

  • 运行时构造任意一个对象

  • 运行取得任意一个类所拥有成员变量和方法

  • 运行时获得任意对象的方法属性

  • 动态代理

how:

1
2
3
Class clazz = Class.forName("全类名");
Class clazz = SomeClass.class;
Class clazz = someClassObj.getClass();

相关操作:可以拿到以下的信息

Constructor:getConstructor, getContructors

Method:getMethods(继承链上public的),getDeclareMethods(当前类声明的所有)

Field:getFields(继承链上public),getDeclareFields(当前类声明所有)

Annotation:getAnnotation,getDeclareAnnotaions(),getParameterAnnotations()

以及newInstance去创建对象

invoke去调用方法

动态代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public interface Boy {
public void print();
}

public class Student implements Boy{
private String name;
private String sex;
private int age;
public void print(){
System.out.println("打印");
}
}

private Boy boy = new Student();
public Boy getProxy(){
return (Boy) Proxy.newProxyInstance(boy.getClass().getClassLoader(), boy.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("我是代理");
return method.invoke(boy,args);
}
});
}