实训28 2018/5/5

反射

  JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象。

  Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。

  

  作为准备工作,先写出Person类,以作演示用:

//Person.java

public class Person {
    //成员变量
    public String name;
    public int age;
    private String address;

    //构造方法
    public Person() {
        System.out.println("空参数构造方法");
    }
    
    public Person(String name) {
        this.name = name;
        System.out.println("带有String的构造方法");
    }
    //私有的构造方法
    private Person(String name, int age){
        this.name = name;
        this.age = age;
        System.out.println("带有String,int的构造方法");
    }
    
    public Person(String name, int age, String address){
        this.name = name;
        this.age = age;
        this.address = address;
        System.out.println("带有String, int, String的构造方法");
    }
    
    //成员方法
    //没有返回值没有参数的方法
    public void method1(){
        System.out.println("没有返回值没有参数的方法");
    }
    //没有返回值,有参数的方法
    public void method2(String name){
        System.out.println("没有返回值,有参数的方法 name= "+ name);
    }
    //有返回值,没有参数
    public int method3(){
        System.out.println("有返回值,没有参数的方法");
        return 123;
    }
    //有返回值,有参数的方法
    public String method4(String name){
        System.out.println("有返回值,有参数的方法");
        return "哈哈" + name;
    }
    //私有方法
    private void method5(){
        System.out.println("私有方法");
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + ", address=" + address+ "]";
    }
}

  获取Class类对象的三种方式:

    方式一:通过Object类中的getObject()方法

Person p=new Person;

Class c=p.getObject();

    方式二:通过 类名.class 获取到字节码文件对象(任意数据类型都具有一个class静态属性)

Class c2 = Person.class;

    方式三:通过Class类中的方法(将类名作为字符串传递给Class类中的静态方法forName())【常用】

Class c3=Class.forName("Person");

  注:

    第三种和前两种的区别:使用前两种时,你必须明确Person类型,而第三种则是指定这种类型的字符串即可。

  通过反射获取构造方法并使用:

    在反射机制中,把类中的成员(构造方法、成员方法、成员变量)都封装成了对应的类进行表示。

    获得构造方法:getConstructor()

    获得多个构造方法:getConstructors()

    

public class ConstructorDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        //1,获取到Class对象
        Class c = Class.forName("cn.itcast_01_Reflect.Person");//包名.类名
        //2,获取指定的构造方法
        //public Person()
        //Constructor con = c.getConstructor(null);
        
        //public Person(String name, int age, String address)
        Constructor con = c.getConstructor(String.class, int.class, String.class);
        
        //3,通过构造方法类中Constructor的方法,创建对象
        //Object obj = con.newInstance(null);
        Object obj = con.newInstance("小明", 22, "哈尔滨");
        
        //显示
        System.out.println(obj);
    }
}

    通过反射方式,可以获得私有构造方法,创建对象(这样做破坏了面向对象的特征之一:封装)——使用setAccessible()方法:

      获取私有构造方法,步骤如下:

      1. 获取到Class对象

      2. 获取指定的构造方法

      3. 暴力访问, 通过setAccessible(boolean flag)方法

      4. 通过构造方法类Constructor中的方法,创建对象 public T newInstance(Object... initargs)

  通过反射获取成员变量并使用:

    在反射机制中,把类中的成员变量使用类Field表示。可通过Class类中提供的方法获取成员变量。

    getField(String name) 获取指定的public修饰的变量

    getDeclaredField(String name) 获取指定的变量(任意修饰都可以获得,即暴力获取)

    getFields() 获得所有public修饰的变量

    getDeclaredFields() 获取所有的变量(包含私有)

    

    获取成员变量,步骤如下:

    1. 获取Class对象

    2. 获取构造方法

    3. 通过构造方法,创建对象

    4. 获取指定的成员变量(私有成员变量,通过setAccessible(boolean flag)方法暴力访问)

    5. 通过方法,给指定对象的指定成员变量赋值或者获取值——set(),get()

  

  通过反射获取成员方法并使用:

    在反射机制中,把类中的成员方法使用类Method表示。可通过Class类中提供的方法获取成员方法。

    getMethod() 获得public修饰的方法

    getDeclaredMethod() 获得任意方法(包括私有的)

    getMethods() 获得本类与父类中所有的public修饰的方法

    getDeclaredMethods() 获取本类中所有的方法(包括私有的)

    

    获取成员方法,步骤如下:

    1. 获取Class对象

    2. 获取构造方法

    3. 通过构造方法,创建对象

               4. 获取指定的方法

               5. 执行找到的方法——invoke()

      

    获取私有成员方法,步骤如下:

    1. 获取Class对象

    2. 获取构造方法

    3. 通过构造方法,创建对象

    4. 获取指定的方法

    5. 开启暴力访问

    6. 执行找到的方法——invoke()

猜你喜欢

转载自www.cnblogs.com/goxxiv/p/8994769.html
今日推荐