20220210 Java 反射基础类
主要的相关类
java.lang.Class
java.lang.reflect.Method
java.lang.reflect.Field
java.lang.reflect.Modifier
java.lang.reflect.Constructor
Class 类
除了int
等基本类型外,Java的其他类型全部都是class
(包括interface
)。
如何获取一个class
的Class
实例?有三个方法:
-
直接通过一个
class
的静态变量class
获取:Class cls = String.class;
-
如果我们有一个实例变量,可以通过该实例变量提供的
getClass()
方法获取:String s = "Hello"; Class cls = s.getClass();
-
如果知道一个
class
的完整类名,可以通过静态方法Class.forName()
获取:Class cls = Class.forName("java.lang.String");
动态加载:JVM在执行Java程序的时候,并不是一次性把所有用到的class全部加载到内存,而是第一次需要用到class时才加载。
/**
* Class 类
*/
public class ClassMain {
public static void main(String[] args) {
// printClassInfo("".getClass());
// printClassInfo(Runnable.class);
// printClassInfo(java.time.Month.class);
// printClassInfo(String[].class);
// printClassInfo(int.class);
// getParentClassInfo();
// getInterface();
getInherit();
}
/**
* 继承关系
* 当我们判断一个实例是否是某个类型时,正常情况下,使用instanceof操作符
* 如果是两个Class实例,要判断一个向上转型是否成立,可以调用isAssignableFrom():
*
*
* 通过Class对象可以获取继承关系:
* Class getSuperclass():获取父类类型;
* Class[] getInterfaces():获取当前类实现的所有接口。
* 通过Class对象的isAssignableFrom()方法可以判断一个向上转型是否可以实现。
*/
private static void getInherit() {
Object n = Integer.valueOf(123);
boolean isDouble = n instanceof Double; // false
boolean isInteger = n instanceof Integer; // true
boolean isNumber = n instanceof Number; // true
boolean isSerializable = n instanceof java.io.Serializable; // true
// Integer i = ?
Integer.class.isAssignableFrom(Integer.class); // true,因为Integer可以赋值给Integer
// Number n = ?
Number.class.isAssignableFrom(Integer.class); // true,因为Integer可以赋值给Number
// Object o = ?
Object.class.isAssignableFrom(Integer.class); // true,因为Integer可以赋值给Object
// Integer i = ?
Integer.class.isAssignableFrom(Number.class); // false,因为Number不能赋值给Integer
}
/**
* 获取interface
* 如果一个类没有实现任何interface,那么getInterfaces()返回空数组。
*/
private static void getInterface() {
Class s = Integer.class;
Class[] is = s.getInterfaces();
for (Class i : is) {
System.out.println(i);
}
// interface java.lang.Comparable
}
/**
* 获取父类的Class
*/
private static void getParentClassInfo() {
Class i = Integer.class;
Class n = i.getSuperclass();
System.out.println(n); // class java.lang.Number
Class o = n.getSuperclass();
System.out.println(o); // class java.lang.Object
System.out.println(o.getSuperclass()); // null
}
static void printClassInfo(Class cls) {
System.out.println("==============================");
System.out.println("Class name: " + cls.getName());
System.out.println("Canonical name: " + cls.getCanonicalName());
System.out.println("Simple name: " + cls.getSimpleName());
if (cls.getPackage() != null) {
System.out.println("Package name: " + cls.getPackage().getName());
}
System.out.println("is interface: " + cls.isInterface());
System.out.println("is enum: " + cls.isEnum());
System.out.println("is array: " + cls.isArray());
System.out.println("is primitive: " + cls.isPrimitive());
}
}
访问字段 Field
public class FieldMain {
public static void main(String[] args) throws Exception {
getFieldTest();
getFieldDetailTest();
}
/**
* Field getField(name):根据字段名获取某个public的field(包括父类)
* Field getDeclaredField(name):根据字段名获取当前类的某个field(不包括父类)
* Field[] getFields():获取所有public的field(包括父类)
* Field[] getDeclaredFields():获取当前类的所有field(不包括父类)
*/
private static void getFieldTest() throws Exception {
System.out.println("=================== getFieldTest ===================");
Class stdClass = Student.class;
System.out.println(Arrays.toString(stdClass.getFields())); // score , name
System.out.println(Arrays.toString(stdClass.getDeclaredFields())); // score , grade
}
private static void getFieldDetailTest() throws Exception {
System.out.println("=================== getFieldDetailTest ===================");
Field f = String.class.getDeclaredField("value");
Class<?> type = f.getType();
int m = f.getModifiers();
System.out.println(f); // private final char[] java.lang.String.value
System.out.println(f.toGenericString());
System.out.println(f.getName()); //
System.out.println(type.getCanonicalName()); // class [B 表示byte[]类型
System.out.println(Modifier.isFinal(m)); // true
System.out.println(Modifier.isPublic(m)); // false
System.out.println(Modifier.isProtected(m)); // false
System.out.println(Modifier.isPrivate(m)); // true
System.out.println(Modifier.isStatic(m)); // false
// 泛型相关
Field f2 = GenericType.class.getDeclaredField("type");
System.out.println(f2); // java.lang.Object reflection.FieldMain$GenericType.type
System.out.println(f2.toGenericString()); // java.lang.Object reflection.FieldMain$GenericType.type
Field f3 = GenericType.class.getDeclaredField("typeList");
System.out.println(f3); // java.util.List reflection.FieldMain$GenericType.typeList
System.out.println(f3.toGenericString()); // java.util.List<T> reflection.FieldMain$GenericType.typeList
}
class GenericType<T>{
T type;
List<T> typeList;
}
class Student extends Person {
public int score;
private int grade;
}
class Person {
public String name;
private String age;
}
}
public class FieldValueMain {
public static void main(String[] args) throws Exception {
Person p = new Person("Xiao Ming");
Class c = p.getClass();
Field f = c.getDeclaredField("name");
f.setAccessible(true); // private 时需要加上
Object value = f.get(p);
System.out.println(value); // "Xiao Ming"
f.set(p, "Xiao Hong");
System.out.println(p.getName()); // "Xiao Hong"
}
}
class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
调用方法 Method
/**
* Method getMethod(name, Class...):获取某个public的Method(包括父类)
* Method getDeclaredMethod(name, Class...):获取当前类的某个Method(不包括父类)
* Method[] getMethods():获取所有public的Method(包括父类)
* Method[] getDeclaredMethods():获取当前类的所有Method(不包括父类)
*/
public class MethodMain {
public static void main(String[] args) throws Exception {
// getMethod();
// invokeMethod();
// invokeStaticMethod();
// invokePrivateMethod();
invokeMultiMethod();
}
/**
* 调用多态方法
*/
private static void invokeMultiMethod() throws Exception {
// 获取Person的hello方法:
Method h = Person.class.getMethod("hello");
// 对Student实例调用hello方法:
h.invoke(new Student()); // Student:hello
/*
相当于:
Person p = new Student();
p.hello();
*/
}
/**
* 调用非public方法
*
* @throws Exception
*/
private static void invokePrivateMethod() throws Exception {
Person p = new Person();
Method m = p.getClass().getDeclaredMethod("setName", String.class);
m.setAccessible(true);
m.invoke(p, "Bob");
System.out.println(p.name);
}
/**
* 通过反射调用静态方法
*
* @throws Exception
*/
private static void invokeStaticMethod() throws Exception {
// 获取Integer.parseInt(String)方法,参数为String:
Method m = Integer.class.getMethod("parseInt", String.class);
// 调用该静态方法并获取结果:
Integer n = (Integer) m.invoke(null, "12345");
// 打印调用结果:
System.out.println(n);
}
/**
* 通过反射调用类方法
*
* @throws Exception
*/
private static void invokeMethod() throws Exception {
// String对象:
String s = "Hello world";
// 获取String substring(int)方法,参数为int:
Method m = String.class.getMethod("substring", int.class);
// 在s对象上调用该方法并获取结果:
String r = (String) m.invoke(s, 6);
// 打印调用结果:
System.out.println(r);
}
private static void getMethod() throws Exception {
Class stdClass = Student.class;
Method method = stdClass.getMethod("getScore", String.class);
System.out.println(Arrays.toString(stdClass.getMethods())); // getScore , getName , Object.wait...
System.out.println(Arrays.toString(stdClass.getDeclaredMethods())); // getGrade , getScore
// 获取public方法getScore,参数为String:
System.out.println(method);
// 获取继承的public方法getName,无参数:
System.out.println(stdClass.getMethod("getName"));
// 获取private方法getGrade,参数为int:
System.out.println(stdClass.getDeclaredMethod("getGrade", int.class));
/**
* getName():返回方法名称,例如:"getScore";
* getReturnType():返回方法返回值类型,也是一个Class实例,例如:String.class;
* getParameterTypes():返回方法的参数类型,是一个Class数组,例如:{String.class, int.class};
* getModifiers():返回方法的修饰符,它是一个int,不同的bit表示不同的含义。
*/
System.out.println(method.getName());
Class<?> returnType = method.getReturnType();
Class<?>[] parameterTypes = method.getParameterTypes();
int modifiers = method.getModifiers();
}
static class Student extends Person {
public void hello() {
System.out.println("Student:hello");
}
public int getScore(String type) {
return 99;
}
private int getGrade(int year) {
return 1;
}
}
static class Person {
public void hello() {
System.out.println("Person:hello");
}
private String name = "personName";
private void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
}
调用构造方法 Constructor
/**
* getConstructor(Class...):获取某个public的Constructor;
* getDeclaredConstructor(Class...):获取某个Constructor;
* getConstructors():获取所有public的Constructor;
* getDeclaredConstructors():获取所有Constructor。
*
* Constructor总是当前类定义的构造方法,和父类无关,因此不存在多态的问题
*/
public class ConstructorMain {
public static void main(String[] args) throws Exception {
// 调用Class.newInstance()的局限是,它只能调用该类的public无参数构造方法。
// 如果构造方法带有参数,或者不是public,就无法直接通过Class.newInstance()来调用。
Integer integer = Integer.class.newInstance();
System.out.println(integer);
// 获取构造方法Integer(int):
Constructor cons1 = Integer.class.getConstructor(int.class);
// 调用构造方法:
Integer n1 = (Integer) cons1.newInstance(123);
System.out.println(n1);
// 获取构造方法Integer(String)
Constructor cons2 = Integer.class.getConstructor(String.class);
Integer n2 = (Integer) cons2.newInstance("456");
System.out.println(n2);
}
}
动态代理
public class ProxyMain {
public static void main(String[] args) {
/**
* 在运行期动态创建一个interface实例的方法如下:
* 1. 定义一个InvocationHandler实例,它负责实现接口的方法调用;
* 2. 通过Proxy.newProxyInstance()创建interface实例,它需要3个参数:
* 2.1. 使用的ClassLoader,通常就是接口类的ClassLoader;
* 2.2. 需要实现的接口数组,至少需要传入一个接口进去;
* 2.3. 用来处理接口方法调用的InvocationHandler实例。
* 3. 将返回的Object强制转型为接口。
*/
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method); // public abstract void reflection.ProxyMain$Hello.morning(java.lang.String)
if (method.getName().equals("morning")) {
System.out.println("Good morning, " + args[0]); // Good morning, Bob
}
return null;
}
};
Hello hello = (Hello) Proxy.newProxyInstance(Hello.class.getClassLoader(), // 传入ClassLoader
new Class[]{Hello.class}, // 传入要实现的接口
handler); // 传入处理调用方法的InvocationHandler
hello.morning("Bob");
}
interface Hello {
void morning(String name);
}
/**
* 把上面的动态代理改写为静态实现类大概长这样:
*/
static class HelloDynamicProxy implements Hello {
InvocationHandler handler;
public HelloDynamicProxy(InvocationHandler handler) {
this.handler = handler;
}
public void morning(String name) {
try {
handler.invoke(this, Hello.class.getMethod("morning", String.class), new Object[]{name});
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
}
}