我的Java学习笔记——反射

学习目标:

搞懂什么是反射


学习内容:

一.关于反射的一些概念

1.反射:主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。也就是能够自描述和自控制。

2.JAVA反射机制:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

3.类对象: 所有的类,都存在一个类对象,这个类对象用于提供类本身的信息,比如有几种构造方法, 有多少属性,有哪些普通方法。

4.实现Java反射机制的API在Java.lang.reflect包下,具有以下几点。
(1)Class类:代表一个类。
(2)Filed类:代表类的成员变量。
(3)Method类:代表类的方法。
(4)Constructor类:代表类的构造方法。
(5)Array类:提供了动态创建数组及访问数组元素的静态方法。该类中的所有方法都是静态的。

二.获取类对象

获取类对象有3种方式
1.Class.forName(包名)

2.类名称.class

3.new 类名称().getClass()

public class TestReflection {
 
    public static void main(String[] args) {
            String className = "包名";
            try {
                Class pClass1=Class.forName(className);
                Class pClass2=Hero.class;
                Class pClass3=new Hero().getClass();
                System.out.println(pClass1==pClass2);//true
                System.out.println(pClass1==pClass3);//true
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
    }
}

获取类对象,会导致静态属性被初始化,而且只会执行一次。(除了直接使用 Class c = 类名称.class 这种方式,这种方式不会导致静态属性被初始化)
在这里插入图片描述

三.创建对象

与传统的通过new 来获取对象的方式不同
反射机制,会先拿到一个“类对象”,然后通过类对象获取“构造器对象”,再通过构造器对象创建一个对象。

public class TestReflection {
  
    public static void main(String[] args) {
        //传统的使用new的方式创建对象
        Hero h1 =new Hero();
        h1.name = "teemo";
        System.out.println(h1);//Hero [name=teemo, hp=0.0, damage=0]
          
        try {
            //使用反射的方式创建对象
            String className = "包名";
            //类对象
            Class pClass=Class.forName(className);
            //构造器
            Constructor c= pClass.getConstructor();
            //通过构造器实例化
            Hero h2= (Hero) c.newInstance();
            h2.name="gareen";
            System.out.println(h2);//Hero [name=gareen, hp=0.0, damage=0]
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

四.访问属性

public class test1 {
    public static void main(String[] args) {
        Hero h =new Hero();
        //使用传统方式修改name的值为garen
        h.name = "garen";
        try {
            //获取类Hero的名字叫做name的字段
            Field f1= h.getClass().getDeclaredField("name");
            //修改这个字段的值
            f1.set(h, "teemo");
            //打印被修改后的值
            System.out.println(h.name);//teemo

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

  • getField和getDeclaredField的区别:
    这两个方法都是用于获取字段。
    getField 只能获取public的,包括从父类继承来的字段。
    getDeclaredField 可以获取本类所有的字段,包括private的,但是不能获取继承来的字段。( 这里只能获取到private的字段,但并不能访问该private字段的值,除非加上setAccessible(true))

五.调用方法

public class r_test {
    public static void main(String[] args) {
        Hero h = new Hero();
        try {
            // 获取这个名字叫做setName,参数类型是String的方法
            Method m = h.getClass().getMethod("setName", String.class);
            // 对h对象,调用这个方法
            m.invoke(h, "盖伦");
            // 使用传统的方式,调用getName方法
            System.out.println(h.getName());

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

六.用反射的作用

  • 在运行时判断任意一个对象所属的类型。
  • 在运行时构造任意一个类的对象。
  • 在运行时判断任意一个类所具有的成员变量和方法。
  • 在运行时调用任意一个对象的方法,甚至可以调用private方法。

另:

  1. 反射是Java语言很重要的特性。
  2. 反射在性能方面会有一定的损耗。
  3. Java语言反射提供一种动态链接程序组件的多功能方法。它允许程序创建和控制任何类的对象,
    无需提前硬编码目标类。这些特性使得反射特别适用于创建以普通方式与对象协作的库。(这一条我没搞懂)在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值