Java基础-反射

本文详细介绍了Java反射机制,包括如何获取Class类实例、创建运行时类的对象、访问类的属性、方法和构造器。通过示例展示了反射在框架中的应用,如动态代理,并探讨了类加载器的工作原理。内容涵盖了反射的各个方面,对于理解Java动态性及框架底层实现非常有帮助。
摘要由CSDN通过智能技术生成

反射机制概述

反射是被视为动态语言的关键, 反射机制允许程序在执行期借助反射API取得任何类的内部信息,并能直接操作任意对象的内部属性和方法;
java文件编译为.class文件后,由类加载器加载后,在堆内存的方法区中就产生了一个一个的Class类型的实例对象,一个类只能有一个Class实例,这个对象实例就包含了完整的类的结构信息.可以通过这个对象实例看到类的结构

Class类实例的获取

Class类实例只能从内存中获取, 无法主动实例化, 因为在.class字节文件被加载至内存时, 就会实例化每一个类的Class实例对象.且一个类只会实例化一个Class对象;
类,接口,数组,注解,枚举,数组,基本数据类型,void都能获取到Class的实例;

	public class ReflectionTest {
		@Test
	    public void test1() throws Exception {
			// 使用各类直接获取
	        Class<Person> clazz = Person.class;
	        System.out.println(clazz);
			// 使用类的实例调用getClass()方法获取
	        Person p = new Person();
	        Class<? extends Person> clazz1 = p.getClass();
	        System.out.println(clazz1);
			// 使用Class.forName(String)方法获取
	        Class<?> clazz2 = Class.forName("com.bryan.study.reflect.Person");
	        System.out.println(clazz2);
			// 使用类加载器获取
	        ClassLoader classLoader = ReflectionTest.class.getClassLoader();
	        Class<?> clazz3 = classLoader.loadClass("com.bryan.study.reflect.Person");
	        System.out.println(clazz3);
	    }
	}

	class Human {
	    private String color;
	
	    private String nation;
	
	    public String cameFrom(){
	        return this.nation;
	    }
	}
	
	@MyAnnotation
	class Person extends Human implements Comparable<Person>{
	
	    @MyAnnotation
	    private String username;
	
	    private String password;
	
	    String mobile;
	
	    public int status;
	
	    public String interest;
	
	    public Person(){
	
	    }
	
	    public Person(String username, String mobile) {
	        this.username = username;
	        this.mobile = mobile;
	    }
	
	    private Person(String username, String mobile, String password, int status){
	        this.username = username;
	        this.mobile = mobile;
	        this.password = password;
	        this.status = status;
	    }
	
	    @MyAnnotation
	    public String work (String job, String boss) throws NullPointerException, ClassCastException{
	        System.out.println("打工人"+this.username+"正在为"+boss+"做"+job+"工作");
	        return job;
	    }
	
	    public static void eat(){
	        System.out.println("吃屎");
	    }
	
	    private void sleep(){
	        System.out.println("睡觉");
	    }
	
	
	    @Override
	    public String toString() {
	        return "Person{" +
	                "username='" + username + '\'' +
	                ", password='" + password + '\'' +
	                ", mobile='" + mobile + '\'' +
	                ", status=" + status +
	                ", interest='" + interest + '\'' +
	                '}';
	    }
	
	    @Override
	    public int compareTo(Person o) {
	        return 0;
	    }
	}
	   
	
	
	@Retention(RetentionPolicy.RUNTIME)
	@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
	@interface MyAnnotation {
	    String value() default "hello";
	}

类的加载过程以及类加载器ClassLoader

在这里插入图片描述
类加载器的作用是用来吧类(Class)装载进内存的, JVM规范定义了如下类型的类加载器:
1.Bootstrap Classloader: 引导类加载器,用C++编写的,是JVM自带的类加载器, 负责Java品台核心库,用来装载核心类库.该加载器无法直接获取;
2.Extesion Classloader: 扩展类加载器, 负责jre/lib/ext目录下的jar包或-D java.ext.dirs 指定目录下的jar包装入工作库;
3.System Classloader: 系统类加载器, 负责java -classpath或-D java.class.path所指的目录下的类与jar包装入工作, 是常用的加载器;
4.自定义加载器;

	public class ReflectionTest {
		@Test
    	public void loaderTest() {
	        // 获取系统类加载器 sun.misc.Launcher$AppClassLoader@18b4aac2
	        ClassLoader classLoader = ReflectionTest.class.getClassLoader();
	        System.out.println(classLoader);
	
	        // 获取扩展类加载器 sun.misc.Launcher$ExtClassLoader@372f7a8d
	        ClassLoader classLoaderParent = classLoader.getParent();
	        System.out.println(classLoaderParent);
	
	        // 无法获取 引导类加载器, 这里获取到的是null
	        ClassLoader bootstrapLoader = String.class.getClassLoader();
	        System.out.println(bootstrapLoader);

			// 使用类加载器读取配置文件
			InputStream is = classLoader.getResourceAsStream("db.properties");
	        Properties p = new Properties();
	        p.load(is);
	        String username = p.getProperty("username");
	        System.out.println(username);
	    }
	}

创建运行时类的对象

何时会用到反射来实例化类的对象: 通常在编译前无法确认需要实例化的类是哪种类,只有在运行时才能确认需要实例化的类时, 才会用到反射来实例化类的对象; 这其实体现出了反射的动态性; 这也就是为什么许多框架底层大量运用了反射机制,利用反射的动态性来处理业务逻辑;

	@Test
    public void newTest() throws IllegalAccessException, InstantiationException {
        Class<Person> clazz = Person.class;
        // 需要运行时类提供足够权限的空参构造器, 否则会报IllegalAccessException,InstantiationException异常
        Person person = clazz.newInstance();
        System.out.println(person);
    }

获取运行时类的完整结构

获取运行时类的属性以及部分源码分析
	@Test
    public void fieldTest() {
        Class<Person> clazz = Person.class;
        // 获取运行时类public修饰的属性以及其父类,接口public修饰的属性
        Field[] fields = clazz.getFields();
        // 获取运行时类所有的属性,无法获取其父类,接口的属性
        Field[] declaredFields = clazz.getDeclaredFields();

        for (Field field: declaredFields) {
            // 获取属性的注解
            Annotation[] annotations = field.getAnnotations();
            for (Annotation a: annotations) {
                System.out.println(a.annotationType().getName());
            }
            // 获取属性的修饰符
            int modifiers = field.getModifiers();
            System.out.print(Modifier.toString(modifiers)+"\t");
            // 获取属性的类型
            Class<?> type = field.getType();
            System.out.print(type.getName()+"\t");
            // 获取属性的名称
            System.out.println(field.getName());
            System.out.println();
        }
    }

	/**源码解析*/
	public final class Class<T> implements java.io.Serializable, GenericDeclaration, Type, AnnotatedElement {
		....
		
		@CallerSensitive
	    public Field[] getFields() throws SecurityException {
	    	// 使得成员属性可访问
	        checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
	        return copyFields(privateGetPublicFields(null));
	    }
		private Field[] privateGetPublicFields(Set<Class<?>> traversedInterfaces) {
	        checkInitted();
	        Field[] res;
	        // 尝试从缓存中获取属性
	        ReflectionData<T> rd = reflectionData();
	        if (rd != null) {
	            res = rd.publicFields;
	            if (res != null) return res;
	        }
	
	        // No cached value available; compute value recursively.
	        // Traverse in correct order for getField().
	        // 没有缓存, 则重新获取
	        List<Field> fields = new ArrayList<>();
	        if (traversedInterfaces == null) {
	            traversedInterfaces = new HashSet<>();
	        }
	
	        // Local fields
	        // 获取运行时类自己的所有属性传true表示只获取public修饰的属性
	        Field[] tmp = privateGetDeclaredFields(true);
	        addAll(fields, tmp);
			
			// 递归调用 获取实现接口的属性
	        // Direct superinterfaces, recursively
	        for (Class<?> c : getInterfaces()) {
	            if (!traversedInterfaces.contains(c)) {
	                traversedInterfaces.add(c);
	                addAll(fields, c.privateGetPublicFields(traversedInterfaces));
	            }
	        }
			// 递归调用 获取父类的属性
	        // Direct superclass, recursively
	        if (!isInterface()) {
	            Class<?> c = getSuperclass();
	            if (c != null) {
	                addAll(fields, c.privateGetPublicFields(traversedInterfaces));
	            }
	        }
	
	        res = new Field[fields.size()];
	        fields.toArray(res);
	        if (rd != null) {
	            rd.publicFields = res;
	        }
	        return res;
	    }
		
		private Field[] privateGetDeclaredFields(boolean publicOnly) {
	        checkInitted();
	        Field[] res;
	        // 尝试从缓存中获取
	        ReflectionData<T> rd = reflectionData();
	        if (rd != null) {
	            res = publicOnly ? rd.declaredPublicFields : rd.declaredFields;
	            if (res != null) return res;
	        }
	        // No cached value available; request value from VM
	        // 获取属性信息并缓存至ReflectionData中
	        res = Reflection.filterFields(this, getDeclaredFields0(publicOnly));
	        if (rd != null) {
	            if (publicOnly) {
	                rd.declaredPublicFields = res;
	            } else {
	                rd.declaredFields = res;
	            }
	        }
	        return res;
	    }
		....
	}
获取运行时类的方法
	@Test
    public void methodTest(){
        Class<Person> clazz = Person.class;
        // 获取运行时类public修饰的方法以及其父类,接口public修饰的方法
        Method[] methods = clazz.getMethods();
        // 获取运行时类所有的方法,无法获取其父类,接口的方法
        Method[] declaredMethods = clazz.getDeclaredMethods();

        for (Method method: declaredMethods) {
            // 获取方法的注解
            Annotation[] annotations = method.getAnnotations();
            for(Annotation a: annotations) {
                System.out.println(a.toString());
            }
            // 获取方法的修饰符
            int modifiers = method.getModifiers();
            System.out.print(Modifier.toString(modifiers)+"\t");

            // 获取方法的返回值
            Class<?> returnType = method.getReturnType();
            System.out.print(returnType.getName()+"\t");
            
            // 获取方法名
            String name = method.getName();
            System.out.print(name);

            System.out.print("(");

            // 获取方法的参数
            Class<?>[] parameterTypes = method.getParameterTypes();
            for (int i = 0 ;i <= parameterTypes.length-1;i++) {
                if (i == parameterTypes.length-1){
                    System.out.print(parameterTypes[i].getName()+" arg" + i);
                    break;
                }
                System.out.print(parameterTypes[i].getName()+" arg" + i+",");
            }

            System.out.print(")\t");

            // 获取方法抛出的异常
            Class<?>[] exceptionTypes = method.getExceptionTypes();
            if (exceptionTypes.length>0) {
                System.out.print("throws\t");
                for (int j = 0 ;j <= exceptionTypes.length-1;j++) {
                    if (j == exceptionTypes.length-1){
                        System.out.print(exceptionTypes[j].getName()) ;
                        break;
                    }
                    System.out.print(exceptionTypes[j].getName()+",");
                }
            }
            System.out.println();
            System.out.println();
        }
    }
获取运行时类的构造器
	@Test
    public void constructorTest(){
        Class clazz = Person.class;
		// 获取运行时类的public修饰的构造器
        Constructor[] constructors = clazz.getConstructors();
		// 获取运行时类的所有构造器
        Constructor[] declaredConstructors = clazz.getDeclaredConstructors();

        for (Constructor c: declaredConstructors) {
			// 获取构造器修饰符
            int modifiers = c.getModifiers();
            // 获取构造器名称
            String name = c.getName();
			// 获取构造器参数
            Class[] parameterTypes = c.getParameterTypes();
        }
    }
获取运行时类的其他结构
	@Test
    public void otherTest(){
        Class<Person> clazz = Person.class;
        Package pack = clazz.getPackage(); // 获取包名
        Class<? super Person> superclass = clazz.getSuperclass(); // 获取父类
        Class<?>[] interfaces = clazz.getInterfaces(); // 获取实现的接口
        Annotation[] annotations = clazz.getAnnotations(); // 获取注解
    }

调用运行时类的指定结构

	@Test
    public void invokeTest() throws IllegalAccessException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
        Class<Person> clazz = Person.class;

        // 实例化
        // Person person = clazz.newInstance();
        // 获取空参构造器
        Constructor<Person> constructor = clazz.getConstructor();
        // 设置构造器可访问
        constructor.setAccessible(true);
        Person person = constructor.newInstance();

        // 获取指定属性
        Field username = clazz.getDeclaredField("username");
        // 设置属性 username 可访问 以防止调用set方法时权限不够
        username.setAccessible(true);
        // 设置属性值 为实例对象person的username属性设置值 bryan
        username.set(person, "bryan");

        System.out.println(person);

        // 获取指定的方法
        Method work = clazz.getMethod("work", String.class, String.class);
        // 设置方法可访问
        work.setAccessible(true);
        // 调用 work 方法 并返回方法的返回值
        Object invoke = work.invoke(person, "编码", "Alex");
        System.out.println(invoke);
    }

动态代理

public class ProxyTest {

    @Test
    public void test(){

        SuperMan s = new SuperMan();

        HumanBean proxy = (HumanBean) ProxyFactory.getProxy(s);

        proxy.work("编码", "Alex");
    }
}

// 被代理類實現的接口
interface HumanBean {

    public String eat();

    public void work(String job, String boss);

}
// 被代理類
class SuperMan implements HumanBean{

    @Override
    public String eat() {
        System.out.println("吃饭");
        return "正在吃饭";
    }

    @Override
    public void work(String job, String boss) {
        System.out.println("打工人为"+boss+"做"+job+"工作");
    }
}

// 代理工廠
class ProxyFactory {

    public static Object getProxy(Object obj){
        Class<?> clazz = obj.getClass();
        MyHandler myHandler = new MyHandler(obj);
        // 創建代理對象 需要 傳入被代理類的類加載器, 被代理類所實現的所有接口, 以及一個回調方法處理器
        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), myHandler);
    }
}

// 回調方法處理器
class MyHandler implements InvocationHandler {
    private Object obj;

    public MyHandler() {
    }

    public MyHandler(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        
        // 回調被代理類方法前可編寫公用的代碼模塊 處理與業務無關的事務, 解耦
        
        // 在處理器中 回調被代理類的方法
        Object invoke = method.invoke(this.obj, args);
        System.out.println("动态代理invoke被调用");
        
        // 回調被代理類方法后可編寫公用的代碼模塊 處理與業務無關的事務, 解耦
        return invoke;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值