反射简介
理解
在运行时可以得到类的一切信息,包括构造器、成员变量、函数、父类、接口、枚举、注解等信息,可以生成对象,就像水中显示实体的倒影一样,称为java的反射机制
条件
- java类经过编译,生成字节码文件,用于表示类
- 字节码文件必须经过虚拟机加载后,在内存中转换为Class对象,才能使用
使用方式
正
- 直接使用new关键字生成对象
- 直接在对象上调用方法等
public class TestReflect {
public static void main(String[] args) {
Phone p = new Phone();
p.setName("verfallen");
p.setPrice(4999);
System.out.println(p);
}
}
反射
- 得到Class对象
- 使用反射API
public class TestReflect {
public static void main(String[] args) {
try {
Class c = Class.forName("com.verfallen.Phone");
Constructor construct = c.getConstructor();
Object o = construct.newInstance();
Method mSetName = c.getMethod("setName", String.class);
Method mSetPrice = c.getMethod("setPrice", int.class);
mSetName.invoke(o, "verfallen1991");
mSetPrice.invoke(o, 5999);
System.out.println(o);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
反射API
获取Class对象的几种方式
forName()
.class
getClass()
public class GetClass {
public static void main(String[] args) throws ClassNotFoundException {
Class c1 = Class.forName("com.verfallen.Phone");
System.out.println(c1.getName());
Class c2 = String.class;
System.out.println(c2.getName());
Class c3 = new Phone().getClass();
System.out.println(c3.getClass().getName());
System.out.println(c1.hashCode() == c3.hashCode());
System.out.println(c1 == c3);
}
}
com.verfallen.Phone
java.lang.String
java.lang.Class
true
true
构造函数
通过Class对象的newInstance()方法,必须有默认构造器
通过Constructor对象的newInstance()方法
package com.verfallen;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class TestConstructor {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class c = Class.forName("com.verfallen.Phone");
Object o1 = c.newInstance();
System.out.println(o1);
// by public constructor
Constructor c1 = c.getConstructor(String.class, int.class);
Object o2 = c1.newInstance("huawei", 5999);
System.out.println(o2);
// by private constructor
Constructor c2 = c.getDeclaredConstructor(int.class);
c2.setAccessible(true);
Object o3 = c2.newInstance(1000);
System.out.println(o3);
}
}
成员函数
package com.verfallen;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestMethod {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class c = Class.forName("com.verfallen.Phone");
Object o = c.newInstance();
Method m1 = c.getMethod("setName", String.class);
m1.invoke(o, "iphone");
System.out.println(o);
Method m2 = c.getDeclaredMethod("GetPriceFromFactor");
m2.setAccessible(true);
System.out.println(m2.invoke(o));
}
}
成员变量
package javase;
import java.lang.reflect.Field;
class Phone {
private int price;
private String name;
public String origin;
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getOrigin() {
return origin;
}
public void setOrigin(String origin) {
this.origin = origin;
}
}
public class TestField {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
Class c = Class.forName("javase.Phone");
Object o = c.newInstance();
Field f1 = c.getDeclaredField("price");
Field f2 = c.getDeclaredField("name");
Field f3 = c.getField("origin");
// 返回修饰符 2表示private
System.out.println(f1.getModifiers());
f1.setAccessible(true);
f1.set(o, 5999);
f1.setInt(o, 9999);
System.out.println(f1.get(o));
f2.setAccessible(true);
f2.set(o, "huawei");
System.out.println(f2.get(o));
f3.set(o, "China");
System.out.println(f3.get(o));
}
}
输出
2
9999
huawei
China