Java筆記(五)反射

  • 獲取運行時類
package test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Demo {
    public static void main(String[] args) {
        Person p = new Person("Lee", 24);
        Class c1 = p.getClass();
        System.out.println(c1);

        Class c2 = Person.class;
        System.out.println(c2);

        Class c3 = null;
        try {
            c3 = Class.forName("test.Person");
            System.out.println(c3);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        ClassLoader classLoader = Demo.class.getClassLoader();
        try {
            Class c4 = classLoader.loadClass("test.Person");
            System.out.println(c4);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        System.out.println(c1 == c2); // true
        System.out.println(c1 == c3); // true
        System.out.println(c1.equals(c2));  // true
        System.out.println(c1.equals(c3));  // true

        System.out.println("-----------------------------------");
        Constructor[] constructors = c1.getConstructors();
        for (Constructor con : constructors) {
            System.out.println(con);
        }
        System.out.println("-----------------------------------");
        try {
            Constructor constructor1 = c1.getConstructor();  // 獲得空參構造方法
            Constructor constructor2 = c1.getConstructor(String.class, int.class);  // 獲得帶參數的構造方法
            Constructor constructor3 = c1.getDeclaredConstructor(int.class, String.class);   // 獲得帶參數的構造方法(私有)
            System.out.println(constructor1);
            System.out.println(constructor2);
            System.out.println(constructor3);
            Person p1 = (Person) constructor1.newInstance();
            Person p2 = (Person) constructor2.newInstance("Jack", 42);
            constructor3.setAccessible(true);   // 取消運行時的權限檢查
            Person p3 = (Person) constructor3.newInstance(17, "Mark");
            System.out.println(p1);
            System.out.println(p2);
            System.out.println(p3);
        } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
            e.printStackTrace();
        }
        System.out.println("-----------------------------------");
        Field[] fileds = c1.getFields();
        for (Field f : fileds) {
            System.out.println(f);
        }
        System.out.println("-----------------------------------");
        fileds = c1.getDeclaredFields();
        for (Field f : fileds) {
            System.out.println(f);
        }
        System.out.println("-----------------------------------");
        try {
            Field field1 = c1.getField("height");  // 公有
            System.out.println(field1);

            Field field2 = c1.getDeclaredField("name");  // 私有
            System.out.println(field2);

            Object obj = c1.newInstance();
            field1.set(obj, 185);
            // field2.set(obj,"Tim");  // 報錯
            System.out.println(obj);
        } catch (NoSuchFieldException | IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
        }
        System.out.println("-----------------------------------");
        Method[] methods = c1.getMethods();
        for (Method m : methods) {
            System.out.println(m);
        }
        System.out.println("-----------------------------------");
        try {
            Method method1 = c1.getMethod("setAge", int.class);
            try {
                Object obj = c1.newInstance();
                method1.invoke(obj, 15);
            } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}

class Person {
    private String name;
    private int age;
    public float height;
    public float weight;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    private Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "test.Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

通過類對象調用newInstance()方法創建對象,默認調用無參數的構造器,初始化新創建的對象,如果這個類沒有默認的構造器,就會拋出一個異常。 所以一般使用Constructor類的newInstance方法去調,可以帶參數,通用一點。

  • 反射類型擦除
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

public class Test{
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add("a");
//        arrayList.add(1);   // invalid
        Class c= arrayList.getClass();
        Method method = null;
        try {
            method = c.getMethod("add",Object.class);
            method.invoke(arrayList,56);
            method.invoke(arrayList,"b");
            method.invoke(arrayList,'c');
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
  • 反射配置文件
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

public class Test {
    public static void main(String[] args) {
        /*
        a.properties
        #className=Person
        #methodName=eat
        className=Student
        methodName=study
        #className=Worker
        #methodName=work
         */
        try(FileReader fr = new FileReader("d:\\a.properties")){
            Properties properties = new Properties();
            properties.load(fr);
            String className = properties.getProperty("className");
            String methodName = properties.getProperty("methodName");
            Class c = Class.forName(className);
            Object obj = c.newInstance();
            Method method = c.getMethod(methodName);
            method.invoke(obj);
        }catch (IOException e){
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

class Person {
    public void eat() {
        System.out.println("eat...");
    }
}

class Student {
    public void study() {
        System.out.println("study...");
    }
}

class Worker {
    public void work() {
        System.out.println("work...");
    }
}

  • 靜態代理
interface PhoneFactory {
    void producePhone();
}

class ProxyPhoneFactory implements PhoneFactory{
    private PhoneFactory phoneFactory;
    ProxyPhoneFactory(PhoneFactory phoneFactory){
        this.phoneFactory = phoneFactory;
    }
    @Override
    public void producePhone() {
        System.out.println("代理工廠開始生產手機");
        phoneFactory.producePhone();
        System.out.println("代理工廠完成生產手機");
    }
}

class MiPhoneFactory implements PhoneFactory{
    @Override
    public void producePhone() {
        System.out.println("生產小米手機");
    }
}

public class StaticProxyTest{
    public static void main(String[] args) {
        // 被代理類
        MiPhoneFactory miPhoneFactory = new MiPhoneFactory();
        // 代理類
        ProxyPhoneFactory proxyPhoneFactory = new ProxyPhoneFactory(miPhoneFactory);

        proxyPhoneFactory.producePhone();
    }
}

  • 動態代理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface Human {
    String getBelief();

    void eat(String food);
}

class SuperMan implements Human {
    @Override
    public String getBelief() {
        return "I can fly!";
    }

    @Override
    public void eat(String food) {
        System.out.println("我喜歡吃" + food);
    }
}

class MyInvocationHandler implements InvocationHandler {
    private Object object;  // 需要使用被代理類的對象進行賦值

    public void bind(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(object, args);
    }
}

class ProxyFactory {
    public static Object getProxyInstance(Object obj) {
        MyInvocationHandler handler = new MyInvocationHandler();
        handler.bind(obj);
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler);
    }
}

public class ProxyTest {
    public static void main(String[] args) {
        SuperMan superMan = new SuperMan();
        Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
        System.out.println(proxyInstance.getBelief());
        proxyInstance.eat("小龍蝦");

        MiPhoneFactory miPhoneFactory = new MiPhoneFactory();
        PhoneFactory phoneFactory = (PhoneFactory) ProxyFactory.getProxyInstance(miPhoneFactory);
        phoneFactory.producePhone();
    }
}

 

參考書籍:《瘋狂Java講義》

參考文章:http://www.runoob.com/java/java-tutorial.html 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章