Java中的反射机制

一、什么是反射?

对于程序员来说,应该很少需要直接使用反射工具;之所以在语言中提供它们,是为了支持其他Java特性,比如对象序列化、Java Beans以及RMI。还有就是在很多框架中,也是应用到了反射机制。

在初学时,只知道这是个生成驱动实例的语句,而这其实就是应用了反射

      // Load the driver
      Class.forName(
        "sun.jdbc.odbc.JdbcOdbcDriver");
      Connection c = DriverManager.getConnection(
        dbUrl, user, password);

二、反射能做什么?

主要的四个功能:
- 获取对象所属的类
- 获取类的成员变量、方法
- 运行时创建对象
- 运行时调用对象的方法

  1. 通过对象获取包名、类名

实例.getClass().getName()

package Reflection;

class Demo {
    // your code here
}

public class Test { ;
    public static void main(String[] args) {
        Demo demo = new Demo();
        System.out.println(demo.getClass().getName());
    }
}
  1. 获取class类

有以下三种方式

package Reflection;

class Demo {
    // your code here
}

public class Test { ;
    public static void main(String[] args) {
        Class<?> demo1 = null;
        Class<?> demo2;
        Class<?> demo3;

        // 1. class.forName("类的路径")
        try {
            demo1 = Class.forName("Reflection.Demo");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        // 2. 实例.getClass()
        demo2 = new Demo().getClass();

        // 3. 类名.class
        demo3 = Demo.class;

        if (demo1 != null) {
            System.out.println(demo1.getName());
        }
        System.out.println(demo2.getName());
        System.out.println(demo3.getName());
    }
}
  1. 运行时创建对象、调用对象的方法
package Reflection;

class Dog {
    private String name;
    private String owner;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getOwner() {
        return owner;
    }

    public void setOwner(String owner) {
        this.owner = owner;
    }

    @Override
    public String toString() {
        return this.name + "'s owner is " + this.owner;
    }
}

public class Test { ;
    public static void main(String[] args) {
        Class<?> demo = null;

        try {
            // 使用反射机制加载类Dog
            demo = Class.forName("Reflection.Dog");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        Dog dog = null;

        // 在运行时动态地创建类Dog的对象
        try {
            dog = (Dog)demo.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        // 运行时调用对象的方法
        if (dog != null) {
            dog.setName("qiuqiu");
        }
        if (dog != null) {
            dog.setOwner("lxb");
        }
        System.out.println(dog);
    }
}

还有需要注意一点的是,如果我们没自定义无参构造函数,而是直接定义了有参构造函数,会报以下错误

null
java.lang.InstantiationException: Reflection.Dog
  at java.lang.Class.newInstance(Class.java:427)
  at Reflection.Test.main(Test.java:49)
Caused by: java.lang.NoSuchMethodException: Reflection.Dog.<init>()
  at java.lang.Class.getConstructor0(Class.java:3082)
  at java.lang.Class.newInstance(Class.java:412)
  ... 1 more

Process finished with exit code 0

所以在程序运行时创建对象时,我们需要自定义无参构造函数

class Dog {
    private String name;
    private String owner;

    // 自定义的无参构造函数
    public Dog() {}

    // 有参构造函数
    public Dog(String name, String owner) {
        this.name = name;
        this.owner = owner;
    }
    // 省略
  }
  1. 其它功能

可用构建器创建新对象,通过Constructor类取得其它类的构造函数

用get()和set()方法读取和修改与Field对象关联的字段

用invoke()方法调用与Method对象关联的方法,即调用其他类的方法

此外,我们可调用方法getFields(),getMethods(),getConstructors(),分别返回用于表示字段、方法以及构建器的对象数组,取得并修改数组的信息

取得其他类的父类、实现的接口、权限修饰符、属性类型等

三、反射的优缺点

  • 优点:可以实现运行时动态创建对象,增加程序的灵活性。这种灵活性怎么体现的呢?比如我们在开发一个大型的软件,编译发布后,我们很可能需要更新一些功能,但因为软件已发布,我们肯定不能要求用户把以前的卸载,再重新安装新的版本。如果我们采用静态的解决方法的话,需要重新编译整个程序,而如果采用反射机制的话,就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现更新的功能。
  • 缺点:
    • 性能影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。
    • 破坏封装,因为通过反射可以访问私有变量或方法,这样可能会存在安全性的问题。比如我们知道String是不可变的,因为这个类被final修饰说明不可继承,并且String其实就是被final修饰的一个字符数组value,value是private的,但是通过反射是可以访问到private成员变量,因此通过反射,我们其实是可以改变String的,很明显,这样是不安全的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值