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() : 获取子类的所有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 name
10 
11 price
12 
13 publicField
14 
15 protectedField
16 
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 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() : 获取子类的所有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.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, 也都是反射的经典例子。

 

你可能感兴趣的:(java反射快速入门(一))