天天看點

Java學習路線-30: 反射與類操作第23 章 : 反射與類操作

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