java 反射

 

反射的意义与作用

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;

这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

反射主要的作用如下:

在运行时判断任意一个对象所属的类

在运行时构造任意一个类的对象

在运行时判断任意一个类所具有的成员变量和方法

在运行时调用任意一个对象的方法

 

 

Java反射机制的实现要借助于4个类:Class,Constructor,Field,Method,反射的实现主要依靠Class类,以下重点阐述Class类。

Class类

 

Class类也是类的一种,只不过是一个比较特殊的类。Class类的对象用于描述某个类的信息(构造器、字段、方法)。

 

得到某个类的Class对象有以下三种方法:

通过该类实例对象的getClass()

        // num为Integer类的实例对象
        Integer num = new Integer(3);
        // 通过num的getClass()方法得到Integer类的Class对象
        Class<?> intClass = num.getClass();

 

使用“类.class”取得

        // 得到Integer类的Class对象
        Class<?> intClass = Integer.class;

 

使用Class类内部定义的一个static方法 forName(String className)

        // 得到Integer类的Class对象
        Class<?> intClass = Class.forName("java.lang.Integer");

 

 

 

Class类对象的作用

得到某个类的Class类对象,该Class对象包含了这个类的所有信息(所有的方法,所有的构造函数,所有的字段)。

通过某个类的Class类对象,可以实现以下功能:

创建该类实例(类似new)

package exercise5;

public class ReflectionTest {


    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {

        // 得到Computer类的Class对象
        Class<?> computerClass = Class.forName("exercise5.Computer");
        // 通过Computer的Class对象computerClass
        // 创建Computer类的实例
        Computer com = (Computer) computerClass.newInstance();
    }
}



class Computer {

    public Computer() {
        System.out.println("A constructor without arguments");
    }

    public Computer(String name) {
        System.out.println("Name is " + name);
    }

    public Computer(String name, int i){
        System.out.println("Name is " + name);
        System.out.println("Price is " + price);
    }


    private String brand;
    public void setBrand(String brand) {this.brand = brand;}
    public String getBrand() {return this.brand;}

    private double price;
    public void setPrice(double price) {this.price = price;}
    public double getPrice() {return this.price;}

}

对于对象的实例化操作,除了使用关键字new之外又多了一个反射机制操作。

 

 

获取该类的构造器对象及使用该对象调用该类的构造器

取得一个类的指定参数构造:public Constructor<T> getConstructor(Class<?>... parameterTypes) 

parameterTypes:方法参数的Class对象

    public static void main(String[] args) throws Exception {

        // 得到Computer类的Class对象
        Class<?> computerClass = Class.forName("exercise5.Computer");
        // 通过Computer的Class对象computerClass获取该类的第二个构造器对象
        Constructor<?> cons = computerClass.getConstructor(String.class);
        // 使用该构造器对象创建实例
        Computer com = (Computer) cons.newInstance("Acer");
    }

 几种获取构造器的方法

public Constructor<?>[] getConstructors()                   获得所有公共构造方法

public Constructor<?>[] getDeclaredConstructors()     获得所有构造方法(包括非public方法)

 

public Constructor<T> getConstructor(Class<?>... parameterTypes)                    获得单个公共构造方法

public Constructor<T> getDeclaredtConstructor(Class<?>... parameterTypes)     获得单个构造方法

 

由上述两个例子可知,类对象computerClass.newInstance()   与   构造器对象cons.newInstance("Acer"); 都可以创建实例。

类对象创建实例,只能调用public 无参的构造函数,相当于通过公共无参构造器对象创建实例。

 

 

 

获取该类的方法对象及使用该对象调用该类的方法

 取得指定方法:public Method getMethod(String name, Class<?>... parameterTypes) 

name:方法名

parameterTypes:方法参数的Class对象

    public static void main(String[] args) throws Exception {

        // 得到Computer类的Class对象
        Class<?> computerClass = Class.forName("exercise5.Computer");
        // 创建Computer类的实例
        Computer com = (Computer) computerClass.newInstance();

        // 获取Computer类的setBrand()方法对象
        Method setMet = computerClass.getMethod("setBrand", String.class);
        // 通过该方法对象,调用com中的setBrand()方法
        setMet.invoke(com, "lenovo");

        // 获取Computer类的getBrand()方法对象
        Method getMet = computerClass.getMethod("getBrand");
        // 通过该方法对象,调用com中getBrand()方法
        System.out.println(getMet.invoke(com));

    }

 

 

  获取该类的属性(字段)对象及使用该对象调用该类的属性

 取得指定的成员:public Field getDeclaredField(String name)

name:成员名字

 

    public static void main(String[] args) throws Exception {

        // 得到Computer类的Class对象
        Class<?> computerClass = Class.forName("exercise5.Computer");
        // 创建Computer类的实例
        Computer com = (Computer) computerClass.newInstance();

        // 获取Computer类的brand字段对象
        Field brandField = computerClass.getDeclaredField("brand");
        // 解除封装
        brandField.setAccessible(true);
        // 使用brandField对象设置com中brand的值
        brandField.set(com, "samsung");
        System.out.println(com.getBrand());
    }

从类的开发要求而言,一直都强调类之中的属性必须封装,所以现在调用之前要想办法解除封装。

解除封装:public void setAccessible(boolean flag) 

getField 可以获取public字段,包括该类所定义的public字段与其所继承的public字段(父类中的public字段、父类的父类中的public字段、...,但不包括Object中的public字段)。
getDeclaredField 可以获取该类本身所定义的字段,包括private、default、protected、public,但是不包括继承来的字段。
getMethod 与 getDeclaredMethod() 相同的道理。

 

 

总结:

反射作用于程序运行阶段,主要通过Class类实现,Class可以获得某个类的Class对象,

通过Class对象可以得到该类的所有信息(属性、构造器、方法),且可以创建该类的实例,调用该类的方法、构造器、属性。

posted on 2018-07-30 19:16  Deltadeblog  阅读(146)  评论(0编辑  收藏  举报

导航