Java反射机制相关

本博文主要分享一些我学习Java反射机制的一些心得体会。

Java反射机制

Java反射机制是指在程序运行时,对于任何一个类,都能知道这个类的所有属性和方法;对于任何一个对象,都能够调用其任何一个属性和方法。这种动态获取信息动态调用对象方法的功能称为Java的反射机制。

简单来说,反射机制可以在程序运行中检查类、接口、方法和变量等信息,不需要知道类名,还可以在运行中实例化新对象(class.newInstance方法)、调用方法。

动态编译和反射机制

为什么要使用反射机制?直接创建对象不好吗?这里涉及到动态和静态编译的概念。

静态编译:在编译时确定类型,绑定对象

动态编译:在运行时确定类型,绑定对象

interface Function{
    void doSomething();
}

class functionA implements Function{
    @Override
    public void doSomething() {
        System.out.println("functionA");
    }
}

class functionB implements Function{
    @Override
    public void doSomething() {
        System.out.println("functionB");
    }
}
public class Test {
    public static void main(String[] args) {
        Function f = new functionA();
//        Function f = new functionB();
        f.doSomething();
    }
}

从上方代码中,我们需要哪个类,只要new一下即可。但这样需要停止程序,修改代码并且重新编译。这种做法对于一个需要不停运行的程序时不允许的(例如服务器),这就需要用到Java的反射机制来实现动态编译。

interface Function{
    void doSomething();
}

class functionA implements Function{
    @Override
    public void doSomething() {
        System.out.println("functionA");
    }
}

class functionB implements Function{
    @Override
    public void doSomething() {
        System.out.println("functionB");
    }
}
public class Test{
    public static void main(String[] args) {
        try {
            //从配置文件读取需要的类名
            String className = getClassNameFromConfig();
            Function f = (Function) Class.forName(className).newInstance();
            f.doSomething();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

使用反射机制,要加载所需要的类型时,只要修改配置文件中的类名即可,不用重新编译。

反射机制的优缺点

  • 优点: 运行期间进行类型判断,动态加载类,提高了代码的灵活性

  • 缺点: 反射相当于一系列解释操作,通知 JVM 要做的事,这样性能要比Java代码直接执行相应操作要慢。

获取Class

在动态编译的情况下,Java 一般有两种方法获取Class对象:

  1. 类名.class
  2. Class.forName(“类名”)
public class Reflect1 {
    public static void main(String[] args) throws ClassNotFoundException {
        // 类名.class
        Class reflect1Class1 = Reflect1.class;
        System.out.println(reflect1Class1.getName());

        // Class.forName
        Class reflect1Class2 = Class.forName("Reflect1");
        System.out.println(reflect1Class2.getName());
		/* 不属于动态加载范畴 */
        // 实例对象.getClass()
        Reflect1 reflect1 = new Reflect1();
        Class reflect1Class3 = reflect1.getClass();
        System.out.println(reflect1Class3.getName());
    }
}

输出结果:

Reflect1
Reflect1
Reflect1

三种获取方式的区别:

类名.class方式适用于在编译时已经知道具体的类; Class.forName()方式适用于运行时动态获取Class对象,因为forName方法会出现找不到类的情况,因此必须捕获 ClassNotFoundException异常;getClass方法针对的是运行时的对象,返回其所属类的Class的对象。

Java反射相关操作

  1. 获取类名 class.getName()
  2. 获取类修饰符 class.getModifiers()
  3. 获取包信息 class.getPackage()
  4. 获取父类的Class对象 class.getSuperclass()
  5. 获取接口信息 class.getInterface()
  6. 获取构造函数 class.getConstructors()
  7. 获取构造函数参数 constructors.getParameterTypes()
  8. 获取Method方法 class.getMethod(), class.getMethods(), class.getDeclaredMethod()
  9. 获取成员变量 class.getField(), class.getFields(), class.getDeclaredField()
  10. … …

这篇文章总结的比较全面:Java反射使用总结

反射的应用场景

  • 使用 JDBC 连接数据库时使用 Class.forName()通过反射加载数据库的驱动程序;
  • Spring 框架的 IOC(动态加载管理 Bean)创建对象以及 AOP(动态代理)功能都和反射有联系;
  • 动态配置实例的属性;
  • … …

好了,关于反射机制,本次就分享到这里,如果文中有任何错误或者欠妥的地方,还望指正。

Life is fantastic!

参考

  1. https://juejin.im/post/6844904005294882830
  2. https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/basic/reflection.md
  3. http://tengj.top/2016/04/28/javareflect/

猜你喜欢

转载自blog.csdn.net/Ahu_hu/article/details/107806830
今日推荐