类型与反射

作者: 写代码的海怪 | 来源:发表于2020-07-01 12:16 被阅读0次

    对于类型与反射,我的理解是在运行时可以动态地对类进行一些操作。

    比如:XXX x = new XXX() 这个 XXX 我是可以外部输入的,输入"Cat" 的时候就是 Cat x = new Cat(),输入"Dog" 的时候,就是 Dog x = new Dog()

    但是这在一般的编程是很难这样动态地做到的,因此需要反射。

    运行 Java 文件的过程

    Java 文件的运行过程是这样的:

    xxx.java -> 编译 -> xxx.class -> 运行
    

    通俗来讲,每个类型要变成一份“说明书”(xxx.class),然后在 new XXX() 的时候是根据这份“说明书”来创建对象的。

    这不禁让我们想到:能不能在运行的时候去修改这份说明书,比如加入变量,修改里面方法等,然后再根据这份“修改过的说明书”去 new 对象呢?

    ClassLoader

    为了去更深入想上面的问题,先来看看这个玩意:ClassLoader,它负责从外部加载一个类,也就是我们的 xxx.java -> 编译 -> xxx.class 这一步。这个很容易理解,就相当于编译器嘛。

    不过它也有下面特点:

    • 对应的 Java 文件不一定存在,可以是 Stream,自己创建 Class
    • 对应的字节码不一定存在,动态创建 Class

    上面的这些特点不禁让我们想到可以“动态地”修改“说明书”了。

    反射

    反射就是可以在运行的时候去修改这份说明书的,然后我们可以调用 ClassLoader 去编译其实就是我们所说的动态XXXX。有了反射,我们可以

    • 动态创建一个对象
    • 动态调用一个方法
    • 动态获取一个属性

    动态创建一个对象

    String className = args[0];
    
    Class c = Class.forName(className);
    
    Object obj = c.getConstructor().newInstance();
    

    动态调用一个方法

    Cat cat = new Cat();
    
    cat.getClass().getMethod(args[0]).invoke();
    

    动态获取一个属性

    Cat cat = new Cat();
    
    cat.getClass().getField(args[0]).get(cat)
    

    双亲委派模型

    看名字就看不懂,意思其实很简单,如果一个类如 String 已经声明,然后你再别的地方再声明 String,那你的 String 并不会被加载。伪代码如下:

    if (java.lang 包里有没有 String 类被加载?) {
      不管了,直接结束
    } else {
      load(自己写的包的 String 类)
    }
    

    相关文章

      网友评论

        本文标题:类型与反射

        本文链接:https://www.haomeiwen.com/subject/ofycqktx.html