Java反射机制

1. Java反射机制概述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 理解Class类并获取Class实例

在这里插入图片描述

3. 类的加载与ClassLoader的理解

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package org.example;

import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
 * 了解类的加载器
 *
 * @author AmorFati
 * @create 2020/10/12 10:55
 */
public class ClassLoaderTest {
    @Test
    public void test1() {
        //对于自定义类,使用系统类加载器进行加载
        ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
        System.out.println(classLoader);
        //调用系统加载器的getParent():获取扩展类加载器
        ClassLoader parent = classLoader.getParent();
        System.out.println(parent);
        //调用扩展类加载器的getParent():无法获取引导类加载器
        //引导类加载器主要负责加载java的核心类库,无法加载自定义类的。
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);
    }

    /*
    Properties:用来读取配置文件
     */
    @Test
    public void test2() throws IOException {
        Properties pros = new Properties();
        //此时的文件默认在当前的module下
        //读取配置文件的方式一:
//        FileInputStream is = new FileInputStream("jdbc.properties");
//        pros.load(is);

        //读取配置文件的方式二:使用ClassLoader
        //配置文件默认识别位:当前module的src下
        ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
        InputStream is = classLoader.getResourceAsStream("jdbc1.properties");
        pros.load(is);

        String user = pros.getProperty("user");
        String password = pros.getProperty("password");
        System.out.println("user=" + user + ",password=" + password);

        is.close();
    }
}

4. 创建运行时类的对象

package org.example;

import org.junit.Test;

import java.util.Random;

/**
 * 通过反射创建对应的运行时类的对象
 *
 * @author AmorFati
 * @create 2020/10/12 11:24
 */
public class NewInstanceTest {
    @Test
    public void test() throws IllegalAccessException, InstantiationException {
        Class<Person> clazz = Person.class;
        /*
        newInstance():调用此方法,创建对应的运行时类的对象
        内部调用了运行时类的空参构造器

        要想此方法正常创建运行时类的对象,要求:
        1.运行时类必须提供空参构造器
        2.空参构造器的访问权限得够。通常,设置为public

        在javabean中通常要求提供一个public的空参构造器,原因:
        1. 便于通过反射,创建运行时类的对象
        2. 便于子类继承此运行时类时,默认调用super()时,保证父类有此构造器
         */
        Person obj = clazz.newInstance();

        System.out.println(obj);
    }

    //体会反射的动态性
    @Test
    public void test2() {

        for (int i = 0; i < 100; i++) {
            int num = new Random().nextInt(3);//0,1,2
            String classPath = "";
            switch (num) {
                case 0:
                    classPath = "java.util.Date";
                    break;
                case 1:
                    classPath = "java.lang.Object";
                    break;
                case 2:
                    classPath = "org.example.Person";
                    break;

            }
            Object obj = null;
            try {
                obj = getInstance(classPath);
                System.out.println(obj);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }

    }

    public Object getInstance(String classPath) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
        Class clazz = Class.forName(classPath);
        return clazz.newInstance();
    }
}

5. 获取运行时类的完整结构

获取运行时类的属性结构及其内部结构

package com.amor;

import org.junit.Test;

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

/**
 * 获取当前运行时类的属性结构
 *
 * @author AmorFati
 * @create 2020/10/12 14:57
 */
public class FieldTest {
    @Test
    public void test1() throws ClassNotFoundException {
        Class clazz = Class.forName("com.amor.Person");

        //获取属性结构
        //getField(): 获取当前运行时类及其父类中声明位public访问权限的属性
        Field[] fields = clazz.getFields();
        for (Field f : fields) {
            System.out.println(f);
        }
        /*
        results:
        public int com.amor.Person.id
        public double com.amor.Creature.weight
         */


        //getDeclaredFields(): 获取当前运行时类中声明的所有属性。(不包含父类中声明的属性)
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field f : declaredFields) {
            System.out.println(f);
        }
        /*
        results:
        private java.lang.String com.amor.Person.name
        int com.amor.Person.age
        public int com.amor.Person.id
         */
    }

    //权限修饰符 数据类型 变量名
    @Test
    public void test2() throws ClassNotFoundException {
        Class clazz = Class.forName("com.amor.Person");
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field f : declaredFields) {
            //1.权限修饰符
            int modifiers = f.getModifiers();
            System.out.print(Modifier.toString(modifiers) + "\t");

            //2. 数据类型
            Class type = f.getType();
            System.out.print(type +"\t");

            //3. 变量名
            String name = f.getName();
            System.out.println(name);
        }
    }
}

获取运行时类的方法结构及其内部结构

package com.amor;

import org.junit.Test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * 获取类的方法的结构
 *
 * @author AmorFati
 * @create 2020/10/12 15:14
 */
public class MethodTest {
    @Test
    public void test1() throws ClassNotFoundException {
        Class clazz = Class.forName("com.amor.Person");

        //getMethods():获取当前运行石磊及其所有父类中声明为public权限的方法

        Method[] methods = clazz.getMethods();
        for (Method m : methods) {
            System.out.println(m);
        }
        /*
        public int com.amor.Person.compare(java.lang.String,java.lang.String)
        public int com.amor.Person.compare(java.lang.Object,java.lang.Object)
        public void com.amor.Person.info()
        public java.lang.String com.amor.Person.display(java.lang.String)
        public java.lang.String com.amor.Person.show(java.lang.String)
        public void com.amor.Creature.eat()
        public final void java.lang.Object.wait() throws java.lang.InterruptedException
        public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
        public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
        public boolean java.lang.Object.equals(java.lang.Object)
        public java.lang.String java.lang.Object.toString()
        public native int java.lang.Object.hashCode()
        public final native java.lang.Class java.lang.Object.getClass()
        public final native void java.lang.Object.notify()
        public final native void java.lang.Object.notifyAll()
        public default java.util.Comparator java.util.Comparator.reversed()
        public default java.util.Comparator java.util.Comparator.thenComparing(java.util.function.Function)
        public default java.util.Comparator java.util.Comparator.thenComparing(java.util.Comparator)
        public default java.util.Comparator java.util.Comparator.thenComparing(java.util.function.Function,java.util.Comparator)
        public default java.util.Comparator java.util.Comparator.thenComparingDouble(java.util.function.ToDoubleFunction)
        public default java.util.Comparator java.util.Comparator.thenComparingInt(java.util.function.ToIntFunction)
        public default java.util.Comparator java.util.Comparator.thenComparingLong(java.util.function.ToLongFunction)
         */
        //getDeclaredMethods():获取当前运行时类中声明的所有方法。(不含父类中声明的方法)
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method m : declaredMethods) {
            System.out.println(m);
        }
        /*
        public int com.amor.Person.compare(java.lang.String,java.lang.String)
        public int com.amor.Person.compare(java.lang.Object,java.lang.Object)
        public void com.amor.Person.info()
        public java.lang.String com.amor.Person.display(java.lang.String)
        public java.lang.String com.amor.Person.show(java.lang.String)
         */
    }

    /*
    @注解
    权限修饰符 返回值类型 方法名(参数类型1 形参名1,...) throws xxxException{}
     */
    @Test
    public void test2() throws ClassNotFoundException {
        Class clazz = Class.forName("com.amor.Person");
        Method[] methods = clazz.getDeclaredMethods();
        for (Method m : methods) {
            //1.获取方法声明的注解
            Annotation[] declaredAnnotations = m.getDeclaredAnnotations();
            for (Annotation a : declaredAnnotations) {
                System.out.print(a + "\t");
            }

            //2. 获取方法的权限修饰符
            System.out.print(Modifier.toString(m.getModifiers()) + "\t");

            //3. 返回值类型
            System.out.print(m.getReturnType().getName() + "\t");

            //4. 方法名
            System.out.print(m.getName() + "\t");

            //5.形参列表
            System.out.print("(");
            Class<?>[] parameterTypes = m.getParameterTypes();
            if (parameterTypes.length != 0) {
                for (int i = 0; i < parameterTypes.length; i++) {
                    if (i == parameterTypes.length - 1) {
                        System.out.print(parameterTypes[i].getName() + " args_" + i);
                        break;
                    }
                    System.out.print(parameterTypes[i].getName() + " args_" + i + ",");
                }
            }
            System.out.print(")");

            //6. 抛出的异常
            Class<?>[] exceptionTypes = m.getExceptionTypes();
            if (exceptionTypes.length != 0) {
                System.out.print(" throws ");
                for (int i = 0; i < exceptionTypes.length; i++) {
                    if (i == exceptionTypes.length - 1) {
                        System.out.print(exceptionTypes[i].getName() + " args_" + i);
                        break;
                    }
                    System.out.print(exceptionTypes[i].getName() + ",");
                }
            }
            System.out.println();
        }

    }

}

框架=注解+反射+设计模式

获取运行时类的构造器结构

package com.amor;

import com.sun.org.apache.xpath.internal.operations.Or;
import org.junit.Test;

import java.lang.reflect.Constructor;

/**
 * 获取构造器
 * @author AmorFati
 * @create 2020/10/12 16:22
 */
public class ConstructorTest {

    @Test
    public void test1() {
        Class clazz = Class.forName("com.amor.Person");
        //getConstructors():获取当前运行时类中声明为public的构造器
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor c : constructors) {
            System.out.println(c);
        }

        //getDeclaredConstructors():获取当前运行时类中声明的所有构造器
        Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
        for (Constructor c : declaredConstructors) {
            System.out.println(c);
        }
    }

}

获取运行时类的父类及父类的泛型

package com.amor;

import org.junit.Test;

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

/**
 * 获取运行时类的父类
 * @author AmorFati
 * @create 2020/10/12 16:28
 */
public class SuperClassTest {
    @Test
    public void test1() throws ClassNotFoundException {

        Class clazz = Class.forName("com.amor.Person");
        //获取运行时类的父类
        Class superclass = clazz.getSuperclass();
        System.out.println(superclass);

        //获取运行时类的带泛型的父类
        Type genericSuperclass = clazz.getGenericSuperclass();
        System.out.println(genericSuperclass);

        //获取泛型类型(重要)
        ParameterizedType paramType = (ParameterizedType) genericSuperclass;
        Type[] actualTypeArguments = paramType.getActualTypeArguments();
//        System.out.println(actualTypeArguments[0].getTypeName());
        System.out.println(((Class) actualTypeArguments[0]).getName());

    }
}

获取运行时类的接口、所在包、注解

package com.amor;

import org.junit.Test;

import java.lang.annotation.Annotation;

/**
 * @author AmorFati
 * @create 2020/10/12 17:23
 */
public class OtherTest {
    //获取运行时类实现的接口
    @Test
    public void test5() throws ClassNotFoundException {
        Class clazz = Class.forName("com.amor.Person");

        Class[] interfaces = clazz.getInterfaces();
        for (Class i : interfaces) {
            System.out.println(i);
        }

    }

    //获取运行时类所在的包
    @Test
    public void test2() throws ClassNotFoundException {
        Class clazz = Class.forName("com.amor.Person");
        Package aPackage = clazz.getPackage();
        System.out.println(aPackage);
    }

    //获取运行时类声明的注解
    @Test
    public void test7() throws ClassNotFoundException {
        Class<?> clazz = Class.forName("com.amor.Person");
        Annotation[] annotations = clazz.getAnnotations();
        for (Annotation a : annotations) {
            System.out.println(a);
        }
    }
}

6. 调用运行时类的指定结构

package com.amor;

import org.junit.Test;

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

/**
 * 调用运行时类中的指定的结构:属性、方法、构造器
 *
 * @author AmorFati
 * @create 2020/10/12 17:32
 */
public class ReflectionTest {
    /*
    通常不采用此方法,使用testField2()中的方法
     */
    @Test
    public void testField() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
        Class clazz = Class.forName("com.amor.Person");
        Person p = (Person) clazz.newInstance();

        //获取指定属性:要求运行时类的属性声明为public
        //所以通常不采用此方法,使用testField2()中的方法
        Field id = clazz.getField("id");

        /*
        设置当前属性的值
        set():参数1,指明设置哪个对象的属性   参数2:将此属性值设置为多少
         */
        id.set(p, 1001);

        /*
        获取当前属性的值
        get():参数1:获取哪个对象的当前属性值
         */
        int pid = (int) id.get(p);
        System.out.println(pid);
    }

    @Test
    public void testField2() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        Class clazz = Class.forName("com.amor.Person");
        Person p = (Person) clazz.newInstance();

        //getDeclaredField(String FieldName):获取运行时类中指定变量名的属性
        Field name = clazz.getDeclaredField("name");
        //保证当前属性是可访问的
        name.setAccessible(true);
        //设定指定对象的此属性值
        name.set(p, "Tom");

        System.out.println(name.get(p));
    }

    /*
    如何操作运行时类中指定的方法--需要掌握
     */
    @Test
    public void testMethod() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Class clazz = Class.forName("com.amor.Person");
        //创建运行时类的对象
        Person p = (Person) clazz.newInstance();

        //1. 获取指定的某个方法
        /*
        1.getDeclaredMethod():参数1:指定获取的方法的名称 参数2:指明获取的方法的形参列表
         */
        Method show = clazz.getDeclaredMethod("show", String.class);
        //2. 保证放啊发是可访问的
        show.setAccessible(true);
        /*
        invoke():参数1:方法的调用者 参数2:给方法形参赋值的实参
        invoke()方法的返回值即为对应类中调用的方法的返回值。
         */
        String returnValue = (String) show.invoke(p, "CHN");
        System.out.println(returnValue);

        //静态方法
        Method showDesc = clazz.getDeclaredMethod("showDesc");
        showDesc.setAccessible(true);
//        showDesc.invoke(Person.class);
        showDesc.invoke(null);//这两个方法都可以
    }

    /*
    如何调用运行时类中的指定的构造器
     */
    @Test
    public void testConstructor() throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException {
        Class clazz = Person.class;
        /*
        1.获取指定的构造器
         */
        Constructor constructor = clazz.getDeclaredConstructor(String.class);

        //2. 保证此构造器是可访问的
        constructor.setAccessible(true);
        //3. 调用此构造器创建运行时类的对象
        Person per = (Person) constructor.newInstance("Tom");
        System.out.println(per);
    }


}

7. 反射的应用:动态代理

代理模式与动态代理

在这里插入图片描述

在这里插入图片描述

静态代理举例

package org.fati;

/**
 * 静态代理举例
 *
 * 特点:代理类和被代理类在编译期间就确定下来了。
 * @author AmorFati
 * @create 2020/10/12 20:33
 */

interface ClothFactory{
    void produceCloth();

}

//代理类
class ProxyClothFactory implements ClothFactory {
   private ClothFactory factory;//就拿被代理类对象进行实例化

    public ProxyClothFactory(ClothFactory factory) {
        this.factory = factory;
    }
    @Override
    public void produceCloth() {
        System.out.println("代理工厂做一些准备工作");

        factory.produceCloth();

        System.out.println("代理工厂做一些后续的首位i工作");
    }
}

//被代理类
class NikeClothfactory implements ClothFactory {
    @Override
    public void produceCloth() {
        System.out.println("Nike工厂生产一批运动服");
    }
}

public class StaticProxyTest {
    public static void main(String[] args) {
//        创建被代理类的对象
        NikeClothfactory nike = new NikeClothfactory();
//        创建代理类的对象
        ProxyClothFactory proxyClothFactory = new ProxyClothFactory(nike);
    }
}



动态代理举例

package org.fati;

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

/**
 * 动态代理的举例
 *
 * @author AmorFati
 * @create 2020/10/12 20:44
 */

interface Human {
    String getBelief();

    void eat(String food);
}

//被代理类
class SuperMan implements Human {
    @Override
    public String getBelief() {
        return "I believe I can fly!";
    }

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


/*
要想实现动态代理,需要解决的问题?
问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象

问题二:当通过代理类的对象调用方法时,如何动态的去调用代理类中的同名方法
 */

class ProxyFactory{
    //调用此方法,返回一个代理类的对象。解决问题一
    public static Object getProxyInstance(Object obj){//obj:被代理类的对象
        MyInvocationHandler handler = new MyInvocationHandler();
        handler.bind(obj);
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler);
    }
}

class MyInvocationHandler implements InvocationHandler{
    private Object obj;//赋值时需要使用被代理类的对象进行赋值

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

    //当我们通过代理类的对象调用方法a时,就会自动的调用如下的方法:invoke()
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //method:即为代理类对象调用的方法,此方法也就作为为了被代理类对象要调用的方法
        //obj:被代理类的对象
        Object returnValue = method.invoke(obj, args);
        return returnValue;
    }
}

public class ProxyTest {

    public static void main(String[] args) {
        SuperMan superMan = new SuperMan();
        //proxyInstance: 代理类的对象
        Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
        //当通过代理类的对象调用方法时,会自动调用被代理类中的同名方法
        String belief = proxyInstance.getBelief();
        System.out.println(belief);
        proxyInstance.eat("四川麻辣烫");
    }

}

AOP与动态代理的举例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值