java反射快速入门(一)

来源:互联网 发布:linux 命令 选项 编辑:程序博客网 时间:2024/06/04 01:33
本文会从以下几个方面讲起

① 反射的简单解释

② 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() : 获取子类的所有private\protected属性

demo如下 : 

private static void demo3() throws Exception {        //  获取父子类的所有public属性        Field[] fields = Airplane.class.getFields();        for(Field f : fields) {            print(f.getName());        }        // 获取子类的所有private\protected属性        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 name10 11 price12 13 publicField14 15 protectedField16 17 --------getDeclaredField(String)------18 19 name
View Code

 

③ 获取方法 

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

getDeclaredMethods() : 获取子类的所有private\protected方法

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 wait10 equals11 toString12 hashCode13 getClass14 notify15 notifyAll16 ------getDeclaredMethods--------17 run18 getName19 setName20 protectedMethod21 privateMethod22 getPrice23 setPrice24 --------getDeclaredMethod------25 getName
View Code

 

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

getConstructors() : 获取public构造函数

getDeclaredConstructors() : 获取子类的所有private\protected\public构造函数 (注意 : 这里还能获取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.Airplanetest.reflect.Airplane-------getDeclaredConstructor(Class<?>)-------test.reflect.AirplaneHighSpeedTrain构造函数是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.HighSpeedTraintest.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);    }// 结果454

 

四、反射应用场景

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

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

 

0 0
原创粉丝点击