Java反射详解

获取类对象的方式

1、Class.forName(全限定类名)
2、通过实例的getClass方法
3、类的.class属性来获取。
注:类对象是一个单例对象。

class Cat {
    private String name;

    public void eat(String food) {
        System.out.println(name + " 正在吃 " + food);
    }

    public Cat(String name) {
        this.name = name;
    }
}

public class TestReflect {
    public static void main(String[] args) throws ClassNotFoundException {
        // 获取类对象, 获取到 Cat 类的说明书.
        // 第一种获取方式是最灵活的. 写代码的时候根本就不需要知道类名. 在实际运行时再获取类名.
        // 第二种和第三种方式都是需要在写代码的时候就要知道类名.
        // 1. 直接通过全限定类名类获取.
        Class catClass = Class.forName("Cat");
        // 2. 通过类的实例来获取
        Cat cat = new Cat("咪咪");
        Class catClass2 = cat.getClass();
        // 3. 通过类来直接获取
        Class catClass3 = Cat.class;

        System.out.println(catClass == catClass2);
        System.out.println(catClass == catClass3);
    }
}

反射

1、定义

Java的反射(reflection)机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到那么,我们就可以修改部分类型信息;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射(reflection)机制。

2、用途

1、在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法 。
2、反射最重要的用途就是开发各种通用框架,比如在spring中,我们将所有的类Bean交给spring容器管理,无论是XML配置Bean还是注解配置,当我们从容器中获取Bean来依赖注入时,容器会读取配置,而配置中给的就是类的信息,spring根据这些信息,需要创建那些Bean,spring就动态的创建这些类。

3、反射基本信息

Java程序中许多对象在运行时会出现两种类型:运行时类型(RTTI)和编译时类型,例如Person p = new Student();这句代码中p在编译时类型为Person,运行时类型为Student。程序需要在运行时发现对象和类的真实信息。而通过使用反射程序就能判断出该对象和类属于哪些类。

4、反射的使用

class Cat {
    private String name = "小猫";

    public Cat() {

    }

    public Cat(String name) {
        this.name = name;
    }

    public void eat(String food) {
        System.out.println(name + " 正在吃 " + food);
    }

    public void eat(String food1, String food2) {
        System.out.println(name + " 正在吃 " + food1 + ", " + food2);
    }
}

借助反射来实例化对象

// 通过反射来实例化对象
    public static void testInstance() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class catClass = Class.forName("Cat");
        // Cat cat = new Cat();
        Cat cat = (Cat) catClass.newInstance();
    }
在这里不使用new关键字也能创建出对象!

借助反射来修改/获取属性

 public static void testField() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        // 1. 先获取到类对象.
        Class catClass = Class.forName("Cat");
        // 2. 借助类对象, 获取到指定的 Field 对象
        //    现在这一步获取到的 field 对象相当于从一个大图纸中获取了一个局部的图纸.
        Field field = catClass.getDeclaredField("name");
        field.setAccessible(true); // 专门处理 private 成员的方式. 破门而入.
        // 3. 根据图纸来修改/获取对象的相关字段
        Cat cat = new Cat();
        // 可以通过 get 方法获取对应属性
        // 也可以通过 set 方法来修改属性
        field.set(cat, "咪咪");
        String name = (String) field.get(cat);
        System.out.println(name);
    }

借助反射来获取/调用方法

public static void testMethod() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        // 1. 先获取到类对象.
        Class catClass = Class.forName("java16_0521.Cat");
        // 2. 根据类对象, 根据名字获取到指定的 Method 对象
        //    getMethod 从第二个参数开始, 其实是用来描述当前 eat 对应的方法应该是哪个版本(当出现 eat 被重载的时候, 能够借助参数列表的类型区分出来).
        Method method = catClass.getMethod("eat", String.class);//    获取到一个参数的版本的 eat
        method.setAccessible(true);
        // Method method = catClass.getMethod("eat", String.class, String.class);//    获取到两个参数的版本的 eat
        // 3. 借助 Method 对象来调用指定的方法(对于非静态方法, 需要指定实例来调用).
        Cat cat = new Cat();
        method.invoke(cat, "鱼");
    }

调用构造方法(也是在创建实例)

public static void testConstructor() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        // 1. 获取类对象
        Class catClass = Class.forName("java16_0521.Cat");
        // 2. 借助类对象获取 Constructor 对象
        //    下面的操作意思是获取到参数为一个 String 的构造方法.
        Constructor constructor = catClass.getConstructor(String.class);
        constructor.setAccessible(true);
        // 3. 根据 Constructor 实例化对象
        Cat cat = (Cat) constructor.newInstance("小黑");

        cat.eat("猫粮");
    }

5、反射的优缺点

优点

  1. 对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法

  2. 增加程序的灵活性和扩展性,降低耦合性,提高自适应能力

  3. 反射已经运用在了很多流行框架如:Struts、Hibernate、Spring 等等。
    缺点

  4. 使用反射会有效率问题。会导致程序效率降低。具体参考这里:http://www.imooc.com/article/293679

  5. 反射技术绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂 。
    主要问题在于Java的反射API设计不够简洁
    注:反射不是一种“常规的编程手段”,不到特殊时刻是不建议使用的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java反射机制是指在运行时动态地获取一个类的信息,并可以操作类的属性、方法和构造器等。Java反射机制可以使程序员在运行时动态地调用类的方法和属性,扩展类的功能,并可以实现注解、工厂模式以及框架开发等。 Java反射机制的原理如下:首先,Java编译器将Java源代码编译为字节码文件,字节码文件中包含着类的信息,这些信息包括类的名称、方法、属性和构造器等等。接着,Java虚拟机将字节码文件加载到内存中,然后通过类加载器将类加载到内存中形成一个类对象,这个类对象可以操作字节码文件中的信息。 使用Java反射机制的过程如下:首先获取类对象,通过类对象来获取类的构造器、属性、方法等信息,然后调用构造器来创建对象,通过属性获取和设置类的成员属性,通过方法调用类的方法等。 Java反射机制的优点是可以在运行时动态地得到类的信息,使得程序员在程序运行时能够对类进行更加灵活的操作,并可以使得程序更加通用化,同时也存在着一定的性能问题,因为Java反射机制需要Java虚拟机进行一定的额外处理,所以在程序运行时需要进行额外的时间和资源消耗。 总之,Java反射机制是Java语言的一项重要特性,在Java开发中广泛应用,在代码编写、框架开发以及API开发中具有重要作用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值