反射的一些基础概念及使用

概念

  • 首先跟大家提一个我个人觉得比较有意思的——关于“反射”这个词汇。百度中对于反射这个词的解释是(偏向于代码中的反射的意思):光线、声波从一种媒质进入另一种媒质时返回原媒质的现象。这个解释我个人认为比较好的解释了java反射机制的核心。
    反射

在JAVA中,反射是指在程序运行时,通过获取到类对象的信息,并将其转化为一个个java对象对其进行访问、修改和调用操作。

  • 注意事项:
    在使用反射时,我们需要使用Java.lang.reflect包中提供的相关类,如Class、Constructor、Method等。通过这些类,我们可以获取一个类的相关信息,并且在运行时创建对象、调用方法等。需要注意的是,使用反射可能会影响程序的性能和安全性,因此不应该滥用。同时,由于反射是在运行时才能确定对象的信息,因此在编写代码时应尽量避免使用字符串硬编码类名等问题,以防止在代码重构时出现问题。

反射的基础使用

1. 获取Class对象

  1. 调用所有类拥有的方法getClass();
    写法:类名.getClass();

    • 实际上,是所有类的父类(Object类)拥有getClass()方法,提供给所有创建的类进行使用。
    • 示例:
    public class Test {
        public static void main(String[] args) {
    		String str = "Hello World";
    		// 使用getClass方法获取类对象
            Class clazz = str.getClass(); 
            // 输出类所属包及类名称
            System.out.println(clazz.getName()); 
        }
    }
    
  2. 调用类的getClass方法获取类对象
    写法:类名.getClass();

    • 任何数据类型(包括基本数据类型)都有一个静态的class属性,同时,都拥有一个调用class属性的get方法
    • 示例:
public class Test {
    public static void main(String[] args) {
	    // 获取int类型的类对象
        System.out.println(int.class); 
        // 获取double类型的类对象
        System.out.println(double.class);
        // 获取String类型的类对象 
        System.out.println(String.class);
    }
}
  1. 调用Class类的forName()方法获取类对象
    写法:Class.forName(“类的名称”);
    • Class.forName方法可能会抛出ClassNotFoundException异常,表示找不到对应的类。需要进行对异常的处理。
    • 示例:
public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        // 调用Class类的forName()方法获取类对象
        System.out.println(Class.forName("java.lang.String").getName());
    }
}
  • 获取类对象时,推荐使用Class.forName(String className)方法获取,这是因为该方法有以下优点:
    1. 可以动态的加载类。在运行时,我们可以根据需要动态地加载一个类,这样就可以在运行时根据一些条件来决定加载哪个类,这种方式比静态的方式更加灵活。
    2. 可以通过类的全限定名来获取类对象。全限定名是唯一的,可以确保获取到的是正确的类对象。
    3. 在JDBC中,通过传递驱动程序类的全限定名,就可以动态地加载对应的驱动程序,从而实现对数据库的访问。
  • 通过刚刚的学习,我们可以发现第一个方式是三个方式中唯一一个使用对象的方式获取类对象。基于我们刚刚提到的——反射本身就是为了获取类对象的操作,在有对象之后就没必要再去获取类对象了。所以,第一种使用频率较低,初步学习时选择使用较多,主要作为一种了解和对类对象的初步学习使用即可。

2. 通过类对象获取成员变量

  • 使用的方法:
    1. getField(String name):获取指定名称的公共(public)成员变量。如果该成员变量不是公共的,则会抛出NoSuchFieldException异常。
    2. getDeclaredField(String name):获取指定名称的成员变量,不考虑修饰符,也就是可以获取到公共的、受保护的、默认的和私有的成员变量。如果该成员变量不存在,则会抛出NoSuchFieldException异常。
      以上两个方法获取到的成员变量对象是Field类型,我们可以通过这个类型的方法来获取或修改成员变量的值。例如:
    // 获取类对象
    Class clazz = MyClass.class;
    // 获取指定名称的成员变量
    Field field = clazz.getField("fieldName");
    // 获取成员变量的值
    Object value = field.get(obj);
    // 修改成员变量的值
    field.set(obj, newValue);
    
  • 需要注意的是,使用getField()方法获取成员变量时,只能获取到公共(public)的成员变量。如果要获取非公共的成员变量,则需要使用getDeclaredField()方法。此外,获取成员变量的值时,需要给该成员变量所属的对象作为参数,如果该成员变量是静态的,则可以传递null作为参数。

3. 通过类对象获取成员方法

  • 使用的方法:

    1. getMethod(String name, Class<?>... parameterTypes):获取指定名称和参数类型列表的公共(public)成员方法。如果该成员方法不是公共的,则会抛出NoSuchMethodException异常。

    2. getDeclaredMethod(String name, Class<?>... parameterTypes):获取指定名称和参数类型列表的成员方法,不考虑修饰符,也就是可以获取到公共的、受保护的、默认的和私有的成员方法。如果该成员方法不存在,则会抛出NoSuchMethodException异常。

    以上两个方法获取到的成员方法对象是Method类型,我们可以通过这个类型的方法来调用成员方法。例如:

    // 获取类对象
    Class clazz = MyClass.class;
    // 获取指定名称和参数类型列表的成员方法
    Method method = clazz.getMethod("methodName", parameterTypes);
    // 调用成员方法
    Object result = method.invoke(obj, args);
    

其中,parameterTypes是一个Class类型的数组,表示成员方法的参数类型列表。args是一个Object类型的数组,表示调用成员方法时传递的具体参数值。

需要注意的是,使用getMethod()方法获取成员方法时,只能获取到公共(public)的成员方法。如果要获取非公共的成员方法,则需要使用getDeclaredMethod()方法。此外,调用成员方法时,需要给该成员方法所属的对象作为参数,如果该成员方法是静态的,则可以传递null作为参数。

希望这篇文章能对你有所帮助。如果有不完整的地方请在评论区进行补充。——W3ak3st

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值