第23 章 : 反射与类操作
104 反射获取类结构信息
反射机制处理不仅仅只是一个实例化对象的处理,
更多情况下还有类的组成结构操作
任何一个类的组成结构:
父类、父接口、包、属性、方法(构造方法,普通方法)
// 获取包名 public Package getPackage() // 获取继承父类 public native Class<? super T> getSuperclass() // 获取实现父接口 public Class<?>[] getInterfaces()
import java.util.Arrays; abstract class AbstractHuman{ } interface IConnectService{ public boolean isConnect(); } interface IChannelService{ public void send(); } class Person extends AbstractHuman implements IConnectService, IChannelService{ @Override public boolean isConnect() { return true; } @Override public void send() { if(this.isConnect()){ System.out.println("发送"); } } } class Demo{ public static void main(String[] args) { Class<?> cls = Person.class; System.out.println(cls.getPackage()); // null System.out.println(cls.getSuperclass()); // class AbstractHuman System.out.println(Arrays.toString(cls.getInterfaces())); // [interface IConnectService, interface IChannelService] } }
105 反射调用构造方法
实例化方法
// 获取指定构造方法 public Constructor<T> getConstructor(Class<?>... parameterTypes) public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) // 获取全部构造方法 public Constructor<?>[] getConstructors() public Constructor<?>[] getDeclaredConstructors() Class.getDeclaredConstructor().newInstance()
class Person{ private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } } class Demo{ public static void main(String[] args) throws Exception { Class<?> cls = Person.class; // 获取有参构造 Constructor constructor = cls.getConstructor(String.class, int.class); Object obj = constructor.newInstance("小强", 23); System.out.println(obj); // Person{name='小强', age=23} } }
使用反射的类最好提供无参构造方法,便于统一操作
继承关系
AccessibleObject(AnnotatedElement) -Executable -Constructor -Method -Field(Member)
106 反射调用普通方法
了解即可
// 获取指定方法 public Method getMethod(String name, Class<?>... parameterTypes) // 获取全部方法 public Method[] getMethods() // 获取本类方法 public Method getDeclaredMethod(String name, Class<?>... parameterTypes) // 获取本类全部方法 public Method[] getDeclaredMethods()
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
class Person { public String geMessage(String message) { return message; } } class Demo { public static void main(String[] args) throws Exception { Class<?> cls = Person.class; Method method = cls.getMethod("geMessage", String.class); System.out.println(method); // public java.lang.String Person.geMessage(java.lang.String) System.out.println(Modifier.toString(method.getModifiers())); // public System.out.println(method.getReturnType().getName()); // java.lang.String System.out.println(method.getName()); // geMessage System.out.println(Arrays.toString(method.getParameterTypes())); // [class java.lang.String] } }
Method类 重要方法 invoke
// 反射调用类中的方法 public Object invoke(Object obj, Object... args)
整个操作形式上没有任何明确的类对象产生,依靠反射操作,避免耦合问题
import java.lang.reflect.Method; class Person { private String name; public Person() { } public Person(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } } class Demo { public static void main(String[] args) throws Exception { Class<?> cls = Class.forName("Person"); String key = "name"; String value = "Tom"; // 获取指定方法 Method setNameMethod = cls.getMethod("setName", String.class); Method getNameMethod = cls.getMethod("getName"); // 调用无参构造方法实例化 Object obj = cls.getDeclaredConstructor().newInstance(); setNameMethod.invoke(obj, value); // 等价于 person.setName(value) System.out.println(getNameMethod.invoke(obj)); // Tom } }
107 反射调用成员
// 获取本类全部成员 public Field[] getDeclaredFields() // 获取本类指定成员 public Field getDeclaredField(String name) // 获取父类全部成员 public Field[] getFields() // 获取父类指定成员 public Field getField(String name)
Field 类
// 设置属性内容 public void set(Object obj, Object value) // 获取属性内容 public Object get(Object obj) // 解除封装 public void setAccessible(boolean flag)
import java.lang.reflect.Field;
class Person { private String name; public Person() { } } class Demo { public static void main(String[] args) throws Exception { Class<?> cls = Class.forName("Person"); Object obj = cls.getDeclaredConstructor().newInstance(); Field nameField = cls.getDeclaredField("name"); // 解除封装性,访问私有成员 nameField.setAccessible(true); nameField.set(obj, "Tom"); System.out.println(nameField.get(obj)); // Tom } }
不建议打破封装机制
Field类重要方法 getType
public Class<?> getType()
Class<?> cls = Class.forName("Person"); Field nameField = cls.getDeclaredField("name"); System.out.println(nameField.getType()); // class java.lang.String System.out.println(nameField.getType().getName()); // 获取包.类 java.lang.String System.out.println(nameField.getType().getSimpleName()); // 获取类名称 String
108 Unsafe工具类
通过反射获取对象,并且直接使用底层的C++代码
可以绕过JVM相关管理机制,就无法使用内存管理和垃圾回收
Unsafe 类
public final class Unsafe { private static final Unsafe theUnsafe; private Unsafe() {} }
Unsafe绕过实例化对象的管理
import sun.misc.Unsafe; import java.lang.reflect.Field; // 将构造函数私有化 class Person{ private Person(){}; public void print(){ System.out.println("hi"); } } class Demo { public static void main(String[] args) throws Exception { Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafeField.setAccessible(true); Unsafe unsafeObject = (Unsafe) theUnsafeField.get(null); // 通过unsafe 实例化构造函数私有化的对象 Person person = (Person) unsafeObject.allocateInstance(Person.class); person.print(); // hi } }
如果不是必须的情况下,不建议使用
Unsafe 类也是单例设计