反射
反射
程序在运行阶段可以拿到某个对象的所有信息
Class类
Class 是 Java 中“描述一个类本身的对象”
JVM为每个加载的class及interface创建了对应的Class实例来保存class及interface的所有信息;
获取一个class对应的Class实例后,就可以获取该class的所有信息;
通过class实例获取class信息的过程就叫“反射”
获取class实例Class的方法
方法1:通过类的静态方法
Class<?> clazz = String.class;方法2:通过对象实例的getClass()方法
String word = "Hollo,World!";
Class<?> clazz = word.getClass();方法3:知道完整类名的情况下使用Class.forName()来获取
class<?> clazz = Class.forName("java.lang.String");访问字段
通过Class实例获取字段(成员变量)的常用方法
Field getField(name):根据字段名获取某个public的field(包括父类)
Field getDeclaredField(name):根据字段名获取当前类的某个field(不包括父类)
Field[] getFields():获取所有public的field(包括父类)
Field[] getDeclaredFields():获取当前类的所有field(不包括父类)
注意
注意:对于使用Field getDeclaredField(name)``Field[] getDeclaredFields()或获取的private 修饰的Field在获取详细的内容时需要先设置 setAccessible(true)
获取字段内容
public class Main {
public static void main(String[] args) throws Exception {
User user = new User("小明",18);
Class<?> clazz = user.getClass();
Field name = clazz.getDeclaredField("name");
name.setAccessible(true);
name.set(user,"李白");
int modifiers = name.getModifiers();
//System.out.println(Modifier.isPublic(modifiers));
Object o = name.get(user);
System.out.println(o);
}
}调用方法
Method getMethod(name, Class...):获取某个public的Method(包括父类)
Method getDeclaredMethod(name, Class...):获取当前类的某个Method(不包括父类)
Method[] getMethods():获取所有public的Method(包括父类)
Method[] getDeclaredMethods():获取当前类的所有Method(不包括父类)
(name, Class...)中的Class...代表参数的Class
public class Main {
public static void main(String[] args) throws Exception {
User user = new User("小明",18);
Class<?> clazz = user.getClass();
Method getName = clazz.getDeclaredMethod("getName");
Object result = getName.invoke(user);
System.out.println(result);
}
}调用构造方法
getConstructor(Class...):获取某个public的Constructor;
getDeclaredConstructor(Class...):获取某个Constructor;
getConstructors():获取所有public的Constructor;
getDeclaredConstructors():获取所有Constructor。
通过反射获取构造器构造User对象
public class Main {
public static void main(String[] args) throws Exception {
Class<?> clazz = User.class;
Constructor<?> constructor = clazz.getConstructor(String.class,int.class);
Object object = constructor.newInstance("小王",19);
User u = (User)object;
System.out.println(u.getName() + " " + u.getAge());
}
}获取继承关系
Class getSuperclass():获取父类类型;
Class[] getInterfaces():获取当前类实现的所有接口。
通过Class对象的isAssignableFrom()方法可以判断一个向上转型是否可以实现。
注意
当我们判断一个实例是否是某个类型时,正常情况下,使用instanceof操作符
//判断B的类型能否转成A A.class.isAssignableFrom(B.class)
父类.class.isAssignableFrom(子类.class)动态代理
可以在运行期动态创建某个interface的实例。
注意
不要在 invoke 里调用 proxy.xxx(),因为调用proxy.xxx()会进入invoke(),一直递归
简单例子
public class Main {
public static void main(String[] args) throws Exception {
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Hello World" + " " + args[0]);
return null;
}
};
Hello hello = (Hello)Proxy.newProxyInstance(Hello.class.getClassLoader(), new Class[]{Hello.class}, handler);
hello.morning("李白");
}
}
public interface Hello {
void morning(String name);
}动态代理的参数
//接口的类加载器,接口Class,InvocationHandler
Proxy.newProxyInstance(Interface.getClassLoader(), new Class[]{Hello.class}, handler)