java基础————反射

                                      ——-android培训java培训、期待与您交流! ———-

 

 


反射(理解)
    (1)类的加载及类加载器
        当程序要使用某个类时,如果该类还未被加载到内存中,
        则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
    加载
        就是指将class文件读入内存,并为之创建一个Class对象。
        任何类被使用时系统都会建立一个Class对象。
    连接
        验证 是否有正确的内部结构,并和其他类协调一致
        准备 负责为类的静态成员分配内存,并设置默认初始化值
        解析 将类的二进制数据中的符号引用替换为直接引用
    初始化 就是我们以前讲过的初始化步骤

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

    一句话来说就是:通过字节码文件对象,去使用成员变量,构造方法,成员方法

    
    (3)反射的使用
    
    我们平时调用类的成员变量,构造方法和成员方法的时候,一般都是通过对象调用的。
        如:
            Student s = new Student();
            p.(成员变量或成员方法);

    反射中我们是怎么使用的呢?
        要像这样使用,首先必须得到class文件对象,其实也就是得到Class类的对象
        Class 类:
            成员变量    Field
            构造方法    Constructor
            成员方法    Method

    获取class文件对象的方式:
        a:Object类的getClass()方法
        b:数据类型的静态属性class
        c:Class类中的静态方法
        public static Class forName(String className)
    那么我们一般用哪个呢?
        a:自己玩    任选一种,第二种比较方便
         b:开发    第三种
          因为第三种是一个字符串,而不是一个具体的类名,
        这样我们就可以把这样的字符串配置到配置文件中。




已知Person类

 

package cn.itcast_01;

public class Person {
    private String name;
    int age;
    public String address;

    public Person() {
    }

    private Person(String name) {
        this.name = name;
    }

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public void show() {
        System.out.println("show");
    }

    public void method(String s) {
        System.out.println("method " + s);
    }

    public String getString(String s, int i) {
        return s + "---" + i;
    }

    private void function() {
        System.out.println("function");
    }

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

}





    A:通过反射获取构造方法并使用
        获取构造方法
        public Constructor[] getConstructors():所有公共构造方法
        public Constructor[] getDeclaredConstructors():所有构造方法
        //遍历该数组获取
        Constructor[] cons = c.getDeclaredConstructors();
        for (Constructor con : cons) {
            System.out.println(con);
        }

        获取单个构造方法
        public Constructor<T> getConstructor(Class<?>... parameterTypes)
        参数表示的是:你要获取的构造方法的构造参数个数及数据类型的class字节码文件对象

        我们一般使用获取单个构造方法
        
        通过带参构造方法对象创建对象
        public T newInstance(Object... initargs)

        使用案例

 

public class ReflectDemo2 {
    public static void main(String[] args) throws Exception {
        // 获取字节码文件对象
        //这里的参数一定是带包名的全名,否则找不到
        Class c = Class.forName("cn.itcast_01.Person");

        // 获取带参构造方法对象
        // public Constructor<T> getConstructor(Class<?>... parameterTypes)
        Constructor con = c.getConstructor(String.class, int.class,
                String.class);

        // 通过带参构造方法对象创建对象
        // public T newInstance(Object... initargs)
        Object obj = con.newInstance("张三", 27, "北京");
        
        System.out.println(obj);
    }
}




    B:通过反射获取成员变量并使用
         获取所有的成员变量
         Field[] fields = c.getFields();            //获取所有公共的的变量的数组
         Field[] fields = c.getDeclaredFields();    //获取所有的变量的数组
         //遍历数组得到变量
         for (Field field : fields) {
            System.out.println(field);
         }
         Field field = c.getField(String name);   //获取单个变量
    
    使用案例

 

public class ReflectDemo {
    public static void main(String[] args) throws Exception {
        // 获取字节码文件对象
        Class c = Class.forName("cn.itcast_01.Person");

        // 通过无参构造方法创建对象
        Constructor con = c.getConstructor();
        Object obj = con.newInstance();
        System.out.println(obj);

        // 获取单个的成员变量
        // 获取address并对其赋值
        Field addressField = c.getField("address");
        // public void set(Object obj,Object value)
        // 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
        addressField.set(obj, "北京"); // 给obj对象的addressField字段设置值为"北京"
        System.out.println(obj);

        // 获取name并对其赋值
        Field nameField = c.getDeclaredField("name");
        //暴力访问
        nameField.setAccessible(true);
        nameField.set(obj, "李四");
        System.out.println(obj);

        // 获取age并对其赋值
        Field ageField = c.getDeclaredField("age");
        ageField.setAccessible(true);
        ageField.set(obj, 27);
        System.out.println(obj);
    }
}




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

     获取所有的方法
         Method[] methods = c.getMethods(); // 获取自己的包括父亲的公共方法
         Method[] methods = c.getDeclaredMethods(); // 获取自己的所有的方法
         //遍历
         for (Method method : methods) {
             System.out.println(method);
         }
     获取单个方法并使用
         public Method getMethod(String name,Class<?>... parameterTypes)
         第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型
    调用方法
         public Object invoke(Object obj,Object... args)
         返回值是Object接收,第一个参数表示对象是谁,第二参数表示调用该方法的实际参数
    使用案例

 

public class ReflectDemo {
    public static void main(String[] args) throws Exception {
        // 获取字节码文件对象
        Class c = Class.forName("cn.itcast_01.Person");


        //获取构造方法
        Constructor con = c.getConstructor();
        //生成对象
        Object obj = con.newInstance();

        /*
         * Person p = new Person(); p.show();
         */

        // 获取单个方法并使用
        // public void show()
        // public Method getMethod(String name,Class<?>... parameterTypes)
        // 第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型
        Method m1 = c.getMethod("show");
        // public Object invoke(Object obj,Object... args)
        // 返回值是Object接收,第一个参数表示对象是谁,第二参数表示调用该方法的实际参数
        m1.invoke(obj); // 调用obj对象的m1方法


        System.out.println("----------");
        
        // public void method(String s)
        Method m2 = c.getMethod("method", String.class);
        m2.invoke(obj, "hello");
        System.out.println("----------");

        // public String getString(String s, int i)
        Method m3 = c.getMethod("getString", String.class, int.class);
        Object objString = m3.invoke(obj, "hello", 100);
        System.out.println(objString);
        // String s = (String)m3.invoke(obj, "hello",100);
        // System.out.println(s);
        System.out.println("----------");

        // private void function()
        Method m4 = c.getDeclaredMethod("function");
        m4.setAccessible(true);
        m4.invoke(obj);
    }
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值