这杯咖啡有毒( ? ) -- Java 的反射机制

public class Creature {
    public double weight;
    public void breath(){
        System.out.println("呼吸!");
    }
}


@MyAnnotation(value = "oktfolio")
public class Person extends Creature implements Comparable, MyInterface {
    public String name;
    private int age;

    public Person() {
    }

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

    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;
    }

    @MyAnnotation(value = "adc")
    public void show() {
        System.out.println("I'm a human.");
    }

    private Integer display(String nation, Integer i) throws Exception {
        System.out.println("I'm from " + nation);
        return i;
    }

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

    @Override
    public int compareTo(Object o) {
        return 0;
    }

    class Bird {
    }

    public static void info() {
        System.out.println("Chinese");
    }

}
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String value();
}
import java.io.Serializable;

public interface MyInterface extends Serializable {
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface Human {
    void info();

    void fly();
}


public class TestAOP {
    public static void main(String[] args) {
        SuperMan superMan = new SuperMan();//创建一个被代理类对象
        Object object = MyProxy.getProxyInstance(superMan);//返回一个代理类的对象
        Human human = (Human)object;
        human.info();//通过代理类的对象调用重写的抽象方法
        human.fly();
    }
}


//被代理类
class SuperMan implements Human {

    @Override
    public void info() {
        System.out.println("I'm superman");
    }

    @Override
    public void fly() {
        System.out.println("I can fly!");
    }
}

class MyInvocationHandler1 implements InvocationHandler {
    Object object;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        HumanUtil humanUtil = new HumanUtil();
        humanUtil.method1();
        Object returnVal = method.invoke(object, args);
        humanUtil.method2();
        return returnVal;
    }
}

class HumanUtil {
    public void method1() {
        System.out.println("===方法一===");
    }

    public void method2() {
        System.out.println("===方法二===");
    }
}


//动态创建一个代理类的对象
class MyProxy {
    public static Object getProxyInstance(Object object) {
        MyInvocationHandler1 handler1 = new MyInvocationHandler1();
        handler1.setObject(object);
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), handler1);
    }
}
//静态代理模式


//接口
interface ClothFactory {
    void productCloth();
}

//被代理类
class NikeClothFactory implements ClothFactory {

    @Override
    public void productCloth() {
        System.out.println("被代理类开始执行...");
    }
}

//代理类
class ProxyFactory implements ClothFactory {
    ClothFactory cf;

    //创建代理类的对象时,实际传入被代理类的对象
    public ProxyFactory(ClothFactory cf) {
        this.cf = cf;
    }

    @Override
    public void productCloth() {
        System.out.println("代理类开始执行...");
        cf.productCloth();
    }
}


public class TestClothProduct {
    public static void main(String[] args) {
        NikeClothFactory nikeClothFactory = new NikeClothFactory();//创建被代理类的对象
        ProxyFactory proxyFactory = new ProxyFactory(nikeClothFactory);//创建代理类的对象
        proxyFactory.productCloth();
    }
}
import org.junit.Test;

import java.lang.reflect.Constructor;

public class TestConstructor {
    @Test
    public void test1() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        String className = "Person";
        Class clazz = Class.forName(className);
        //创建运行时类的对象。使用 newInstance(),实际上就是调用了运行时类的空参的构造器。
        //要想能够创建成功:①要求对应的运行时类需要有空参的构造器 ②构造器的权限修饰符的权限要足够。
        Person p = (Person) clazz.newInstance();
        System.out.println(p);
    }

    @Test
    public void test2() throws ClassNotFoundException {
        String className = "Person";
        Class clazz = Class.forName(className);
        Constructor[] constructors = clazz.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
    }
}
import org.junit.Test;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class TestField {
    //获取对应的运行时类的属性
    @Test
    public void test1() {
        Class clazz = Person.class;
        //getFields():只能获取到运行时类及其父类中声明为 public 的属性
        Field[] fields = clazz.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        //getDeclaredFields();获取运行时类本身声明的所有的属性。
        Field[] fields1 = clazz.getDeclaredFields();
        for (Field field : fields1) {
            System.out.println(field);
        }
    }


    //权限修饰符 Modifiers 变量类型 Type 变量名 Name
    @Test
    public void test2() {
        Class clazz = Person.class;
        Field[] fields = clazz.getFields();
        for (Field field : fields) {
            //1.获取每个属性的权限修饰符
            System.out.print(Modifier.toString(field.getModifiers()) + " ");
            //2.获取属性的变量类型
            System.out.print(field.getType() + " ");
            //3.获取属性名
            System.out.println(field.getName());
        }
    }

    //调用运行时类中指定的属性
    @Test
    public void test3() throws NoSuchFieldException, IllegalAccessException, InstantiationException {
        Class clazz = Person.class;
        //1.获取指定的属性
        //getField(String fieldName):获取运行时类中声明为 public 的指定属性名为 fieldName 的属性
        Field name = clazz.getField("name");
        //2.创建运行时类的对象
        Person p = (Person) clazz.newInstance();
        System.out.println(p);
        //3.将运行时类的指定的属性进行赋值
        name.set(p, "Jerry");
        System.out.println(p);

        System.out.println();
        //getDeclaredField(String fieldName):获取运行时类中的指定属性名为 fieldName 的属性
        Field age = clazz.getDeclaredField("age");
        age.setAccessible(true);//私有方法需要setAccessible(true)才能操作私有属性
        age.set(p, 10);
        System.out.println(p);
    }
}
import com.sun.xml.internal.ws.api.model.ExceptionType;
import org.junit.Test;

import javax.sound.midi.Soundbank;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class TestMethod {
    //1.获取运行时类的方法

    @Test
    public void test1() {
        Class clazz = Person.class;
        //getMethods():只能获取到运行时类及其父类中声明为 public 的方法
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        //getDeclaredMethods():获取运行时类本身声明的所有的方法
        Method[] methods1 = clazz.getDeclaredMethods();
        for (Method method : methods1) {
            System.out.println(method);
        }
    }


    //注解 Annotation 权限修饰符 Modifiers 返回值类型 ReturnType 参数列表 异常
    @Test
    public void test2() {
        Class clazz = Person.class;
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            //1.注解
            Annotation[] annotations = method.getAnnotations();
            for (Annotation annotation : annotations) {
                System.out.println(annotation);
            }
            //2.权限修饰符
            System.out.print(Modifier.toString(method.getModifiers()) + " ");

            //3.返回值类型
            System.out.print(method.getReturnType() + " ");

            //4.方法名
            System.out.print(method.getName());

            //5.参数列表
            System.out.print("(");
            Class[] classes = method.getParameterTypes();
            for (int i = 0; i < classes.length; i++) {
                System.out.print(classes[i].getName() + " args-" + i + "");
            }
            System.out.print(")");

            //6.异常
            Class[] exceptionTypes = method.getExceptionTypes();
            if (exceptionTypes.length != 0) {
                System.out.print("throws ");
            }
            for (int i = 0; i < exceptionTypes.length; i++) {
                System.out.print(exceptionTypes[i].getName());
            }
            System.out.println();
        }
    }

    //调用运行时类中指定的方法
    @Test
    public void test3() throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Class clazz = Person.class;
        //getMethod(String methodName,Class..params):获取运行时类中声明为 public 的方法。
        Method method = clazz.getMethod("show");
        Person p = (Person) clazz.newInstance();

        //调用指定的方法:invoke(Object obj,Object ...obj)
        Object returnVal = method.invoke(p);


        Method method1 = clazz.getMethod("toString");
        Object returnVal1 = method1.invoke(p);
        System.out.println(returnVal1);


        //对于运行时类中的 static 方法调用
        Method method2 = clazz.getMethod("info");
        method2.invoke(Person.class);


        //getDeclaredMethod(String methodName,Class ...params):获取运行时类中的
        Method method3 = clazz.getDeclaredMethod("display", String.class, Integer.class);
        method3.setAccessible(true);
        Object returnVal2 = method3.invoke(p, "China", 10);
        System.out.println(returnVal2);
    }


    //调用指定的构造器
    @Test
    public void test4() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        String className = "Person";
        Class clazz = Class.forName(className);
        Constructor constructor = clazz.getDeclaredConstructor(String.class, int.class);
        constructor.setAccessible(true);
        Person p = (Person) constructor.newInstance("Tom",16);
        System.out.println(p);
    }
}
import org.junit.Test;

import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public class TestOthers {

    //1.获取运行时类的父类
    @Test
    public void test1() {
        Class clazz = Person.class;
        Class superClass = clazz.getSuperclass();
        System.out.println(superClass);
    }

    //2.获取带泛型的父类
    @Test
    public void test2() {
        Class clazz = Person.class;
        Type type = clazz.getGenericSuperclass();
        System.out.println(type);
    }

    //3.获取父类的泛型
    @Test
    public void test3() {
        Class clazz = Person.class;
        Type type = clazz.getGenericSuperclass();
        ParameterizedType parameterizedType = (ParameterizedType) type;
        Type[] types = parameterizedType.getActualTypeArguments();
        for (Type type1 : types) {
            System.out.println(((Class)type1).getName());
        }
    }

    //4.获取实现的接口
    @Test
    public void test4(){
        Class clazz = Person.class;
        Class[] interfaces = clazz.getInterfaces();
        for (Class anInterface : interfaces) {
            System.out.println(anInterface);
        }
    }

    //5.获取所在的包
    @Test
    public void test5(){
        Class clazz = Person.class;
        Package aPackage = clazz.getPackage();
        System.out.println(aPackage);
    }

    //6.获取注解
    @Test
    public void test6(){
        Class clazz = Person.class;
        Annotation[] annotations = clazz.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
    }

}
//动态代理的使用


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface Subject {
    void action();
}

//被代理类
class RealSubject implements Subject {

    @Override
    public void action() {
        System.out.println("被代理类执行");
    }
}

class MyInvocationHandler implements InvocationHandler {
    Object object;//实现了接口的被代理类的对象的声明

    //①给被代理的对象实例化 ②返回一个代理类的对象
    public Object bind(Object object) {
        this.object = object;
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
    }

    //当通过代理类的对象发起对被重写的方法的调用时,都会转换为对如下的 invoke 方法的调用
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //method 方法的返回值是 returnVal
        Object returnVal = method.invoke(object, args);
        return returnVal;
    }
}


public class TestProxy {
    public static void main(String[] args) {
        //1.被代理类的对象
        RealSubject realSubject = new RealSubject();
        //2.创建一个实现了 InvocationHandler 接口的对象
        MyInvocationHandler handler = new MyInvocationHandler();
        //3.调用 bind() 方法,动态的返回一个同样实现了 real 所在类实现的接口 Subject 的代理类的对象
        Object object = handler.bind(realSubject);
        Subject subject = (Subject) object;//此时的 subject 就是代理类的对象
        /*Object returnVal = */
        subject.action();//转到 InvocationHandler 接口的实现类的 invoke() 方法调用
        /* System.out.println(returnVal);*/


        //再举一个例子

        NikeClothFactory nikeClothFactory = new NikeClothFactory();

        MyInvocationHandler handler1 = new MyInvocationHandler();

        ClothFactory clothFactory = (ClothFactory) handler1.bind(nikeClothFactory);

        clothFactory.productCloth();


    }
}
import org.junit.Test;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

public class TestReflection {

    //关于类的加载器 ClassLoader
    @Test
    public void Test5() throws ClassNotFoundException, IOException {
        ClassLoader classLoader = ClassLoader.getSystemClassLoader();
        System.out.println(classLoader);

        ClassLoader classLoader1 = classLoader.getParent();
        System.out.println(classLoader1);

        ClassLoader classLoader2 = classLoader1.getParent();
        System.out.println(classLoader2);

        Class clazz = Person.class;
        ClassLoader classLoader3 = clazz.getClassLoader();
        System.out.println(classLoader3);

        String className = "java.lang.Object";
        Class clazz1 = Class.forName(className);
        ClassLoader classLoader4 = clazz1.getClassLoader();
        System.out.println(classLoader4);

        //掌握
        //法一:
        ClassLoader classLoader5 = this.getClass().getClassLoader();
        InputStream is = classLoader5.getResourceAsStream("jdbc.properties");
        //法二:
        FileInputStream fis = new FileInputStream(new File("jdbc.properties"));

        Properties properties = new Properties();
        properties.load(is);
        String username = properties.getProperty("username");
        System.out.println(username);
        String password = properties.getProperty("password");
        System.out.println(password);
    }

    //如何获取 Class 的实例
    @Test
    public void test4() throws ClassNotFoundException {
        //1.调用运行时类本身的 .class 属性。
        Class clazz = Person.class;
        System.out.println(clazz.getName());
        Class clazz1 = String.class;
        System.out.println(clazz1.getName());

        //2.通过运行时类的对象获取
        Person p = new Person();
        Class clazz2 = p.getClass();
        System.out.println(clazz2.getName());

        //3.通过 Class 的静态方法获取。体现反射的动态性。
        String className = "Person";
        Class clazz3 = Class.forName(className);
        System.out.println(clazz3.getName());

        //4.通过类的加载器ClassLoader
        ClassLoader classLoader = this.getClass().getClassLoader();
        Class clazz4 = classLoader.loadClass(className);
        System.out.println(clazz4.getName());
    }

    /*
     * java.lang.Class: 是放射的源头。
     *
     * 我们创建了一个类,通过编译 ( javac.exe ) ,生成对应的 .class 文件。
     * 之后我们用 java.exe 加载 ( JVM 的类加载器 ) 此 .class文件。
     * 此 .class 文件加载到内存以后,就是一个运行时类,存在缓存区。
     * 那么这个运行时类本身就是一个 Class 的示例。
     *
     * 1.每一个运行时类只加载一次!
     * 2.有了 Class 的实例以后,我们才可以进行如下的操作。
     *  1)*创建对应的运行时类的对象
     *  2)获取对应的运行时类的完整结构(属性、方法、构造器、内部类、父类、所在的包、异常、注解、...)
     *  3)*调用对应的运行时类指定的结构(属性、方法、构造器)
     *  4)反射的应用:动态代理
     * */
    @Test
    public void test3() {
        Person p = new Person();
        Class clazz = p.getClass();//通过运行时类的对象,调用其 getClass() 方法返回其运行时类
        System.out.println(clazz);
    }


    //有了反射,可以通过反射创建一个类的对象, 并调用其中的结构
    @Test
    public void test2() throws IllegalAccessException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
        Class clazz = Person.class;

        //1.创建 clazz 对应的运行时类 Person 类的对象。
        Person p = clazz.newInstance();
        System.out.println(p);

        //2.通过反射调用运行时类指定的属性
        //2.1 public
        Field f1 = clazz.getField("name");
        f1.set(p, "Tony");
        System.out.println(p);

        //2.2 private
        Field f2 = clazz.getDeclaredField("age");
        f2.setAccessible(true);
        f2.set(p, 15);
        System.out.println(p);


        Method m1 = clazz.getMethod("show");
        m1.invoke(p);

        Method m2 = clazz.getMethod("display", String.class);
        m2.invoke(p, "Zhongguo");
    }


    // 在有反射以前,如何创建一个类的对象,并调用其中的方法、属性。
    @Test
    public void test1() throws Exception {
        Person p = new Person();
        p.setAge(18);
        p.setName("Jack");
        p.show();
        //p.display("China");
        System.out.println(p);
    }
}

你可能感兴趣的:(Java)