第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 類也是單例設計