• java反射快速入门(一)


    本文会从以下几个方面讲起

    ① 反射的简单解释

    ② java反射的API接口 及 demo

    ③ 反射的优缺点、应用场景

    一、什么是反射?

    java反射:在程序运行中动态获取类的信息,及动态调用对象的方法,这就是java反射

    二、java反射的API接口

    常用API接口规律  

    getXX() : 获取类本身 及父类的public属性、方法等

    getDeclaredXX() :  获取类本身的所有私有保护属性、方法等

    getDeclaredXX(String name) : 获取类本身的指定name的私有、保护属性、方法等(getDeclaredConstructors 较特殊, 还可以获取public)

    以下demo涉及到的类先给出咯

    package test.reflect;
    
    // 父类
    public abstract class Vehicle {
        
        public String superField = "父类属性";
        
        private String superPrivateField = "父类私有属性";
        
        protected String superProtectedField = "父类保护属性";
    
        public abstract void run();
        
        private void superPrivateMethod() {
            
        }
        
        protected void superProteMethod() {
            
        }
    }
    
    // 飞机子类
    package test.reflect;
    
    public class Airplane extends Vehicle {
    
        private String name;
    
        private int price;
        
        public String publicField;
        
        protected String protectedField;
        
        private Airplane() {
            System.out.println("Airplane 构造函数");
        }
        
        public Airplane(String name, int price) {
            this.name = name;
            this.price = price;
        }
    
        public void run() {
    
            System.out.println("春节,坐飞机飞回家~~~");
        }
        
        protected void protectedMethod() {
            
        }
        
        private void privateMethod() {
            
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getPrice() {
            return price;
        }
    
        public void setPrice(int price) {
            this.price = price;
        }
    
    }
    // 高铁子类
    package test.reflect;
    
    public class HighSpeedTrain extends Vehicle {
    
        private String name;
    
        private int price;
    
        public void run() {
    
            System.out.println("春节,坐高铁溜回家~~~");
        }
        
        private HighSpeedTrain() {
            
        }
        
        protected HighSpeedTrain(String name) {
            
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getPrice() {
            return price;
        }
    
        public void setPrice(int price) {
            this.price = price;
        }
    
    }

    ① 使用反射构建对象

    1 private static void demo2() throws Exception {
    2         
    3         Class.forName("test.reflect.Airplane").newInstance();
    4         
    5         Airplane.class.newInstance();
    6         
    7         
    8         Airplane.class.getDeclaredConstructor(new Class[]{}).newInstance(); // new Class[]{} 使用无惨构造函数
    9     }

    所有类都是Class对象, 获取class 有以下三种

    Class.forName(包名+类名)

    xx.class

    xx.getClass

    ②  获取属性 

    getFields() : 获取父子类的所有public属性

    getDeclaredFields() : 获取子类的所有privateprotected属性

    demo如下 : 

    private static void demo3() throws Exception {
            //  获取父子类的所有public属性
            Field[] fields = Airplane.class.getFields();
            for(Field f : fields) {
                print(f.getName());
            }
            // 获取子类的所有privateprotected属性
            Field[] fields2 = Airplane.class.getDeclaredFields();
            for(Field f : fields2) {
                print(f.getName());
            }
            // 获取指定属性名的属性
            Field f = Airplane.class.getDeclaredField("name");
            print(f.getName());
        }


    结果

     1 -------getFields-------
     2 
     3 publicField
     4 
     5 superField
     6 
     7 -------getDeclaredFields-------
     8 
     9 name
    10 
    11 price
    12 
    13 publicField
    14 
    15 protectedField
    16 
    17 --------getDeclaredField(String)------
    18 
    19 name
    View Code

    ③ 获取方法 

    getMethods() : 获取父子类的所有public方法

    getDeclaredMethods() : 获取子类的所有privateprotected方法

    demo如下 : 

        private static void demo4() throws Exception {
    
            Method[] methods = Airplane.class.getMethods();
            for(Method m : methods) {
                print(m.getName());
            }
            
            
            Method[] methods2 = Airplane.class.getDeclaredMethods();
            for(Method m : methods2) {
                print(m.getName());
            }
            
            
            Method m = Airplane.class.getDeclaredMethod("getName");
            print(m.getName());
            
        }

    结果 :

     1 ------getMethods--------
     2 run
     3 getName
     4 setName
     5 getPrice
     6 setPrice
     7 wait
     8 wait
     9 wait
    10 equals
    11 toString
    12 hashCode
    13 getClass
    14 notify
    15 notifyAll
    16 ------getDeclaredMethods--------
    17 run
    18 getName
    19 setName
    20 protectedMethod
    21 privateMethod
    22 getPrice
    23 setPrice
    24 --------getDeclaredMethod------
    25 getName
    View Code

    ④  获取构造函数(和前面有所区别,指类本身的构造函数,不包括父类)

    getConstructors() : 获取public构造函数

    getDeclaredConstructors() : 获取子类的所有privateprotectedpublic构造函数 (注意 : 这里还能获取public的, 和 getDeclaredFields getDeclaredMethods 不同)

    demo如下 :

    Airplane构造函数是public修饰
    private static void demo5() throws Exception {
            
            Constructor<?>[] constructors = Airplane.class.getConstructors();
            for(Constructor c : constructors) {
                print(c.getName());
            }
            
            System.out.println("--------------");
            Constructor<?>[] constructors2 = Airplane.class.getDeclaredConstructors();
            for(Constructor c : constructors2) {
                print(c.getName());
            }
            
            System.out.println("--------------");
            Constructor<Airplane> c = Airplane.class.getDeclaredConstructor(new Class[]{String.class, int.class});
            print(c.getName());
            
        }
    // 结果
    -------getConstructors-------
    test.reflect.Airplane
    -------getDeclaredConstructors-------
    test.reflect.Airplane
    test.reflect.Airplane
    -------getDeclaredConstructor(Class<?>)-------
    test.reflect.Airplane
    
    HighSpeedTrain构造函数是private protected修饰
    private static void demo6() throws Exception {
            
            System.out.println("------getConstructors--------");
            Constructor<?>[] constructors = HighSpeedTrain.class.getConstructors();
            for(Constructor c : constructors) {
                print(c.getName());
            }
            
            System.out.println("------getDeclaredConstructors--------");
            Constructor<?>[] constructors2 = HighSpeedTrain.class.getDeclaredConstructors();
            for(Constructor c : constructors2) {
                print(c.getName());
            }
        }
    // 结果
    ------getConstructors--------
    ------getDeclaredConstructors--------
    test.reflect.HighSpeedTrain
    test.reflect.HighSpeedTrain

      三、java 反射的优缺点

    ① 优点 :

    • 在运行时检测对象的类型;
    • 动态构造某个类的对象;
    • 检测类的属性和方法;
    • 任意调用对象的方法;
    • 修改构造函数、方法、属性的可见性;
    • 以及其他。

    ② 缺点 :性能下降 . 由于反射涉及动态解析类型, 所以使用反射构建对象 比 直接构造对象性能差了一两个数量级

        private static void demo7() throws Exception {
            
            long start = System.currentTimeMillis();
            for(int i = 0; i <  10000; i++) {
                Airplane a = new Airplane();
            }
            System.out.println(System.currentTimeMillis() - start);
            
            start = System.currentTimeMillis();
            for(int i = 0; i <  10000; i++) {
                Airplane a2 = Airplane.class.getDeclaredConstructor().newInstance();
            }
            System.out.println(System.currentTimeMillis() - start);
        }
    // 结果
    4
    54

    四、反射应用场景

    ① junit test, 使用注解@Test , 底层无非是使用反射来获取加了Test的注解标识,从而获取到测试方法。

    ② spring aop思想, spring 加载bean xml 配置文件, 使用 Class.forName(String beanName) 动态构造bean, 也都是反射的经典例子。

  • 相关阅读:
    js获取日期周数
    PowerDesigner 生成SQL Server 注释脚本
    HTML中的&nbsp; &ensp; &emsp; 等6种空格标记
    创建Windows任务计划定时调用网页执行任务(通过Windows PowerShell的Invoke-WebRequest实现)
    提取全局应用程序集中的dll
    silverlight发布设置
    PowerDesigner 生成SQL Server 2005 注释脚本
    .net core 发布时视图Views文件夹不被打打包成.dll文件解决办法
    .net core 如何使用Senparc.Weixin 给指定的用户发送消息
    js禁止浏览器的回退事件
  • 原文地址:https://www.cnblogs.com/chenmo-xpw/p/5182950.html
Copyright © 2020-2023  润新知