主要用两种形式:java
为何不用RTTI,由于它有一个限制:类型必须是在编译期间已知的。web
Java反射机制是在运行状态中,对于任意一个类,都可以知道这个类的全部属性和方法。对于一个对象,都可以调用它的任意方法和属性。api
这种动态获取信息以及动态调用对象的方法的功能称为Java语言的反射机制。svg
要想使用反射机制,就必需要先获取该类的字节码文件对象(.class),经过字节码文件对象,就可以经过该类中的方法获取到咱们想要的全部信息(方法、属性、类名、父类、实现的全部接口等等)。spa
在运行期,一旦咱们想生成那个类的一个对象,用于执行程序的JVM首先会检查那个类型的class对象是否已经载入。若还没有载入,JVM就会查找同名的.class文件,并将其载入。code
每个类对应着一个字节码文件也就对应着一个class类型的对象,也就是字节码文件对象。xml
在反射中,要获取一个类或调用一个类的方法,咱们首先须要获取到该类的class对象。对象
首先咱们介绍一下动态加载和静态加载。继承
动态加载:程序在运行时调用相应方法,即便其余方法是错误的,程序依旧会执行。经过动态加载可让程序的可延长性大大提高,对之后的维护和扩展有重要意义。接口
静态加载:程序在编译时执行。在执行过程当中加载全部可能执行到的程序。在这种加载方式下,只要加载中一个方法出错,程序就不能运行。咱们通常写程序默认的是静态加载。
有三种方法:
Class.forName(类名)
Class clz = String.class
只适合在编译前就知道要操做的Class。 obj.getClass()。
第一种有更好的扩展性,因此通常状况下,第一种用的较多。
有两种方式:
经过Class对象的newInstance()
方法
Class clz = Person.class;Person per = (Person)clz.newInstance();
经过Constructor对象的newInstance()
Class clz = Person.class; Constructor constructor = clz.getConstructor(); Person per = (Person)constructor.newInstance();
Class clz = Person.class;
Constructor constructor = clz.getConstructor(String.class, int.class);
Person per = (Person)constructor.newInstance("小明", 15);
经过class对象的getFields()
能够获取到class的非私有属性。
经过class对象的getDeclaredFields()
方法能够获取包括私有属性在内的全部属性。
经过class对象得getMethods
获取该类中的全部方法,包括继承和实现的方法。
经过class对象得getDeclaredMethods
获取该类中的全部方法(包括私有方法),不包括包括继承方法。
PS:私有方法和私有属性不能直接访问,由于权限不够。不过仍是有办法的。
method.setAccessible(true)
field.setAccessible(true)
经过反射,咱们能够调用其它类的私有方法。
import java.lang.reflect.Method;
class A
{
private void pow(int n)
{
System.out.println(n * n);
}
}
class Test
{
public static void main(String args[]) throws Exception
{
Class<A> c = A.class;
Object obj = c.newInstance();
Method m = c.getDeclaredMethod("pow", new Class[]{ int.class });
m.setAccessible(true);//修改访问权限
m.invoke(obj, 4);//调用方法
}
}