![](https://img.haomeiwen.com/i5460809/600dbcc5be8ce819.jpeg)
什么是RTTI
在运行期间,就是你的程序可以发现和使用运行时类型信息。而RTTI的本身就是在运行时识别一个对象的类型。
反射的作用
在运行期,对于任意的一个类,可以完成获取其所有的属性,方法,注解,类型信息并且还可以执行其方法和引用属性等操作。
下文操作的实体
@SuppressWarnings("unchecked")
public class ReflectModel implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String name;
public int age;
private double price;
private Long num;
private boolean isDeleted;
public ReflectModel() {}
public ReflectModel(String name) {
this.name = name;
System.out.println("ReflectModel init " + name);
}
private String method1(String mName) {
return mName;
}
public void method2(String name, int age, boolean isDeleted) {
}
public static double method3() {
return 3d;
}
public void method4() {
}
}
java.lang.Class类的创建
- Class.forName方式
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("cn.spy.test.ReflectModel");
System.out.println(clazz.newInstance());
}
结果:
cn.spy.test.ReflectModel@53606bf5
说明:一旦类的Class对象被载入了内存,它就被用来创建这个类的所有对象。如果我们想要在运行时使用类型的信息,就必须首先得获取对应的Class对象的引用。因为Class.forName的形式获取类的结果在编译期是不可知的,所以毫无疑问,如果找不到加载的类,就会报找不到类的异常。
-
对象.getClass()方式
如果我们已经拥有了类的对象,可以采用getClass方法来获取类的引用;返回Class类对象。 -
字面量方式:类名.class方式
当使用 .class 方式来创建对Class对象的引用时,不会自动初始化该Class对象。
public class ReflectTest {
public static void main(String[] args) throws Exception {
Class<Apple> appleClazz = Apple.class;
// static final修饰的变量类未被初始化
System.out.println("static final name : " + Apple.name);
System.out.println("------------------------------------");
// static修饰的变量类执行了初始化
System.out.println("static price : " + Apple.price);
System.out.println("------------------------------------");
// Class.forName方式初始化了对象
Class<?> clazz = Class.forName("cn.spy.test.Orange");
}
}
class Apple {
static final String name = "apple";
static int price = 20;
static {
System.out.println("Now Class is Apple");
}
}
class Orange {
static String name = "orange";
static {
System.out.println("Now Class is Orange");
}
}
![](https://img.haomeiwen.com/i5460809/afdf34741b4f54c7.jpg)
说明:
① 字面量.class方式创建对象不会马上初始化对象。
② Class.forName方式创建对象会马上进行初始化操作。
③ 字面量.class方式引用静态不可变的属性将不会执行初始化,引用静态非不可变的属性将会执行初始化。(理由:final修饰的类变量在类加载的准备阶段就进行初始化操作,根本不用等到初始化阶段进行初始化操作。而jvm规范中规定了在初始化阶段,如果执行了引用了类的静态非final的变量这种主动引用方式,那么将会对类进行初始化操作)
运行时获取包信息
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("cn.spy.test.ReflectModel");
// 包信息
Package pack = clazz.getPackage();
System.out.println("getPackage : " +pack);
System.out.println("getPackage - getName : " + pack.getName());
// 接口信息
Class<?>[] iClazzArr = clazz.getInterfaces();
for (Class<?> iClazz : iClazzArr) {
System.out.println("getInterfaces - getName : " + iClazz.getName());
System.out.println("isInterface : " + iClazz.isInterface());
}
// 注解信息
SuppressWarnings suppressWarnings = clazz.getAnnotation(SuppressWarnings.class);
System.out.println(suppressWarnings);
}
![](https://img.haomeiwen.com/i5460809/6128196039f40b45.jpg)
运行时获取变量信息
public class ReflectTest {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("cn.spy.test.ReflectModel");
Field f1 = clazz.getDeclaredField("name");
Field f2 = clazz.getField("age");
System.out.println("f1.getName() : " + f1.getName());
System.out.println("f2.getName() : " + f2.getName());
System.out.println(f1.isAccessible());
f1.setAccessible(true);
Object instance = clazz.newInstance();
f1.set(instance, "sunpy");
System.out.println(f1.get(instance));
Field[] fieldArr = clazz.getFields();
for (Field field : fieldArr) {
System.out.println(field.getName() + " - " + field.get(clazz.newInstance()));
}
Field[] declaredFieldArr = clazz.getDeclaredFields();
for (Field declaredField : declaredFieldArr) {
declaredField.setAccessible(true);
System.out.println(declaredField.getName() + " -> " + declaredField.get(clazz.newInstance()));
}
}
}
![](https://img.haomeiwen.com/i5460809/c5ef03d59941f5af.jpg)
运行时获取方法信息
public class ReflectTest {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("cn.spy.test.ReflectModel");
Method method3 = clazz.getMethod("method3");
System.out.println("method3 : " + method3.getName());
Method method2 = clazz.getDeclaredMethod("method2", String.class,int.class,boolean.class);
System.out.println("method2 : " + method2);
Method method1 = clazz.getDeclaredMethod("method1", String.class);
method1.setAccessible(true);
System.out.println(method1.invoke(clazz.newInstance(), "sunpy execute method1"));
Method[] methodArr = clazz.getMethods();
for (Method m : methodArr) {
System.out.println(m);
}
System.out.println("------------------------------");
Method[] declaredMethodArr =clazz.getDeclaredMethods();
for (Method m : declaredMethodArr) {
System.out.println(m);
}
System.out.println("------------------------------");
Constructor<?> c = clazz.getConstructor(String.class);
System.out.println(c.newInstance("sunpy"));
clazz.getConstructors();
}
}
结果:
method3 : method3
method2 : public void cn.spy.test.ReflectModel.method2(java.lang.String,int,boolean)
sunpy execute method1
public static double cn.spy.test.ReflectModel.method3()
public void cn.spy.test.ReflectModel.method2(java.lang.String,int,boolean)
public int cn.spy.test.ReflectModel.method4(int)
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()
------------------------------
public static double cn.spy.test.ReflectModel.method3()
public void cn.spy.test.ReflectModel.method2(java.lang.String,int,boolean)
private java.lang.String cn.spy.test.ReflectModel.method1(java.lang.String)
public int cn.spy.test.ReflectModel.method4(int)
------------------------------
ReflectModel init sunpy
cn.spy.test.ReflectModel@dd41677
网友评论