zoukankan      html  css  js  c++  java
  • 【Java语言特性学习之二】反射

    一、概念
    java加载class文件分两种情况:
    (1)类型是编译器已知的,这种文件的.class文件在编译的时候,编译器会把.class文件打开(不加载)检查,称为Run- Time Type Identification 运行时类型识别
    (2)从其它地方获取引用,然后动态的把这个未知类型的引用的对象的.class文件加载进jvm虚拟机里,称为反射;

    在运行状态中,动态获取类信息(属性、方法)及动态调用类对象方法的功能称为java的反射机制。

    二、反射API
    Java反射包:java.lang.reflect.*
    1、获取类
    首先获取类,获取到类之后,Class类提供了很多获取类属性,方法,构造方法的api
    (1)obj.getClass(),这个是Object类里面的方法;
    (2)User.Class属性,任何的数据类型,基本数据类型或者抽象数据类型,都可以通过这种方式获取类;
    (3)Class.forName(""),Class类提供了这样一个方法,让我们通过类名来获取到对象类,使用最多;

    package reflect;
    
    import reflect.test.model.User;
    
    public class Main {
    
        public static void main(String[] args) throws ClassNotFoundException {
            
            //1.通过Object类里面的方法getClass()
            User u = new User();
            Class c = u.getClass();
            System.out.println(c);//class reflect.test.model.User
    
            //2通过.Class属性
            Class c2 = User.class;
            System.out.println(c2);//class reflect.test.model.User
            
            //3.Class.forName("全路径名")
            Class c3 = Class.forName("reflect.test.model.User");
            System.out.println(c3);//class reflect.test.model.User
        }
    }

    2、获取属性和方法

    package reflect.test.model;
    
    public class User {
        
        private String name;
        
        private int age;
        
        public User() {}
        public User(String name,int age) {
            this.name = name;
            this.age = age;
        }
        
        public int a = 100;
        
        private String str = "123456789";
        
        public boolean dosomething(Integer a,Float b) {
            System.out.println("dosomething");
            return true;
        }
    
    }
    package reflect;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    
    public class Main2 {
    
        public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException {
    
            /************************获取所有的属性************************/
            Class<?> c = Class.forName("reflect.test.model.User");
            //getDeclaredFields 获取所有的属性
            Field[] fs = c.getDeclaredFields();
    
            // 定义可变长的字符串,用来存储属性
            StringBuffer sb = new StringBuffer();
            // 通过追加的方法,将每个属性拼接到此字符串中
            // 最外边的public定义
            sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() + "{
    ");
            // 里边的每一个属性
            for (Field field : fs) {
                sb.append("	");// 空格
                sb.append(Modifier.toString(field.getModifiers()) + " ");// 获得属性的修饰符,例如public,static等等
                sb.append(field.getType().getSimpleName() + " ");// 属性的类型的名字
                sb.append(field.getName() + ";
    ");// 属性的名字+回车
            }
    
            sb.append("}");
    
            System.out.println(sb);
            
            /***************************获取指定属性***********************/
            
            //获取id属性  
            Field idF = null;
            try {
                idF = c.getDeclaredField("age");
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (SecurityException e) {
                e.printStackTrace();
            }  
            //实例化这个类赋给o  
            Object o = null;
            try {
                o = c.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
            }  
            //打破封装  
            idF.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。  
            //给o对象的id属性赋值"110"  
            try {
                //set  
                idF.set(o,110);
            } catch (IllegalArgumentException | IllegalAccessException e) {
                e.printStackTrace();
            } 
            //get  
            try {
                System.out.println(idF.get(o));
            } catch (IllegalArgumentException | IllegalAccessException e) {
                e.printStackTrace();
            }
            
            /***************************获取方法****************************/
            
            //getDeclaredMethods()    获取所有的方法(不包含构造方法)
            Method[] declaredMethods = c.getDeclaredMethods();
            for (Method m:declaredMethods) {
                System.out.println(m);
                //getReturnType()    获得方法的放回类型
                System.out.println(m.getReturnType());
                //getParameterTypes()    获得方法的传入参数类型
                Class<?>[] parameterTypes = m.getParameterTypes();
                for(Class cc : parameterTypes) {
                    System.out.println(cc);
                }
            }
    
            //getDeclaredMethod("方法名",参数类型.class,……)    获得特定的方法
            Method declaredMethod = c.getDeclaredMethod("dosomething", Integer.class,Float.class);
            System.out.println(declaredMethod);
            Method method = c.getMethod("dosomething", Integer.class,Float.class);
            System.out.println(method);
            //getDeclaredConstructors()    获取所有的构造方法
            Constructor<?>[] declaredConstructors = c.getDeclaredConstructors();
            for(Constructor ccc : declaredConstructors) {
                System.out.println(ccc);
            }
            //getDeclaredConstructor(参数类型.class,……)    获取特定的构造方法
            Constructor<?> declaredConstructor = c.getDeclaredConstructor(String.class,int.class);
            System.out.println(declaredConstructor);
            //getSuperclass()    获取某类的父类
            Class<?> superclass = c.getSuperclass();
            System.out.println(superclass);
            //getInterfaces()    获取某类实现的接口
            Class<?>[] interfaces = c.getInterfaces();
            for(Class cccc: interfaces) {
                System.out.println(cccc);
            }
            
            
        }
    
    }

    结果:

    public class User{
        private String name;
        private int age;
        public int a;
        private String str;
    }
    110
    public boolean reflect.test.model.User.dosomething(java.lang.Integer,java.lang.Float)
    boolean
    class java.lang.Integer
    class java.lang.Float
    public boolean reflect.test.model.User.dosomething(java.lang.Integer,java.lang.Float)
    public boolean reflect.test.model.User.dosomething(java.lang.Integer,java.lang.Float)
    public reflect.test.model.User()
    public reflect.test.model.User(java.lang.String,int)
    public reflect.test.model.User(java.lang.String,int)
    class java.lang.Object

    三、反射应用--动态代理

    package reflect.test.intf;
    
    public interface Interface {
    
        public void dosomething() ;
    }
    package reflect.test.intf.impl;
    
    import reflect.test.intf.Interface;
    
    public class InterfaceImpl implements Interface {
    
        @Override
        public void dosomething() {
            System.out.println("dosomething");
        }
    
    }

    1、静态代理

    package reflect;
    
    import reflect.test.intf.Interface;
    import reflect.test.intf.impl.InterfaceImpl;
    
    /**
     * 静态代理
     */
    public class HandProxy implements Interface{
        
        Interface inter = new InterfaceImpl();
    
        @Override
        public void dosomething() {
            System.out.println("静态代理类");
            inter.dosomething();
        }
    
    }
    package reflect;
    
    public class TestHandProxy {
    
        public static void main(String[] args) {
    
            HandProxy p = new HandProxy();
            p.dosomething();
        }
    
    }
    结果:
    静态代理类 dosomething

    2、动态代理

    package reflect;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * 动态代理
     */
    public class AutoProxy implements InvocationHandler{
        private Object target;
        
        public Object bind(Object target) {
            this.target = target;
            /**
             * 第一个是被代理类的类构造器,
             * 第二个指的是被代理类的接口,也就是Interface接口,
             * 第三个是实现这个代理的类,这里就是本类。
             * 这个方法执行了下面三步:
                1.生成一个实现了参数interfaces里所有接口且继承了Proxy的代理类的字节码,然后用参数里的classLoader加载这个代理类。
                2.使用代理类父类的构造函数 Proxy(InvocationHandler h)来创造一个代理类的实例,将我们自定义的InvocationHandler的子类传入。
                3.返回这个代理类实例,因为我们构造的代理类实现了interfaces(也就是我们程序中传入的target.getClass().getInterfaces())里的所有接口,因此返回的代理类可以强转成Interface类型来调用接口中定义的方法。
             */
            return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object result = null;
            System.out.println("动态代理");
            result = method.invoke(target, args);
            System.out.println("动态代理执行结束");
            return result;
        }
    
    }
    package reflect;
    
    import reflect.test.intf.Interface;
    import reflect.test.intf.impl.InterfaceImpl;
    
    public class TestAutoProxy {
    
        public static void main(String[] args) {
            Interface inter = new InterfaceImpl();
            AutoProxy ap = new AutoProxy();
            Interface obj = (Interface)ap.bind(inter);
            obj.dosomething();
        }
    
    }

    结果:

    动态代理
    dosomething
    动态代理执行结束
  • 相关阅读:
    JSR 303
    Spring JSR-250注解
    java 内部类
    爬虫
    多线程异步编程示例和实践-Task
    多线程异步编程示例和实践-Thread和ThreadPool
    线程机制、CLR线程池以及应用程序域
    二维码的生成与识别
    Unicode 和 UTF-8 有何区别?
    json转换为自定义类型的集合
  • 原文地址:https://www.cnblogs.com/cac2020/p/11996790.html
Copyright © 2011-2022 走看看