Java反射是很重要的一部分内容。许多框架都是基于Java反射机制加上各种设计模式,比如常用的工厂模式,代理模式等,来实现框架强大的功能。
class / interface的数据类型是Class,class是Java关键字而Class是一种类型(Type)。
Class是什么?怎么创建?
JVM会为每一个加载的class文件创建Class类型的实例,相比于普通的类型,Class的构造方式是private的,我们没有办法手动创建Class实例,Class实例是由JVM内部创建的,我们只能获取。
常用的String类的Class实例的内部字段如下:
字段 | 值 |
---|---|
name | “java.lang.String” |
package | “java.lang” |
super | java.lang.Object |
interface | java.io.Serializable, Comparable, CharSequence |
field | value[],hash,… |
method | indexOf,… |
通过Class实例获取信息的方法称作反射。
怎么获取Class?
有三种方法获取String的Class,以String为例:
Class c1 = String.class;
Class c2 = "123".getClass();
Class c3 = Class.forName("java.lang.String");
由于Class实例在JVM中是唯一的,Class实例可以直接用==
比较。
instanceof
用来判断某个实例是不是某个Class的实例或其子类的实例,要注意区分。
动态加载
在获取Class的三种方法中,Type.class和getClass方法总是要在代码中确定这个类,可以使用Class.forName动态加载,例如JDBC驱动就是这么加载的。
Class实例常用方法有哪些?
获取名字,实例化:
Class c = String.class;
c.getName(); //"java.lang.String"
c.getSimpleName(); //"String"
c.getPackage().getName(); //"java.lang"
String s= (String)c.newInstance(); //调用 public 无参构造函数,无法带参数
访问字段:
//获取Field对象
getField(String name) //获取某个public field(包括父类)
getFields() //获取所有public field(包括父类)
getDeclaredField(name) //获取当前类的某个field(不包括父类)
getDeclaredFields() //获取当前类的所有field(不包括父类)
//Field对象的方法
getName(); //字段名字
getType(); //字段类型
get(Object); //获取该字段的值
set(Object,Object); //设置该字段的值
setAccessible(true); //上述get方法单独使用无法访问private字段,可以使用此方法跳过安全检查
调用方法:
//获取Method对象
getMethod(String name) //获取某个public method(包括父类)
getMethods() //获取所有public method(包括父类)
getDeclaredMethod(name) //获取当前类的某个method(不包括父类)
getDeclaredMethods() //获取当前类的所有method(不包括父类)
//Method对象的方法
getName(); //方法名字
getReturnType(); //返回类型
getParameterTypes(); //参数类型
Object invoke(Object instance,Object... args) //调用方法
更多具体的方法可以参考实现类。