java - 反射不返回正确的实例

标签 java

我对反射有丰富的经验。首先是一些示例代码:

public abstract class A {

    public A () {
        init();
    }

    public abstract void init ();
}


public class B extends A {

    private int i = 0;

    public B () {
        super();
        System.out.println(i);
    }

    public void init () {
        i = 1;
    }
}

在我的代码中的某处,我使用反射 api 来实例化对象 B。

Class<AbstractSection> bc = (Class<AbstractSection>) Class.forName(B);
Constructor<?> bcon = bc.getConstructor();
B b = (B) bcon.newInstance();

我期望的是 B 的一个实例,其中变量 i 设置为值“1”。我得到的是 B 的一个实例,我仍然设置为“0”。 通过调试器仔细观察,我发现这并不完全正确:i 仍未设置为“0”。它在中更改为“1” init() 方法并在 super() 调用返回的那一刻设置回“0”。

有人知道吗?提前致谢,

曼纽尔

PS:我知道我可以通过不在父类(super class)中而是在继承构造函数中调用 init() 来解决这个问题。

最佳答案

对于初学者来说,这与反射无关 - 如果您自己实例化该类,您会得到相同的结果。

您的困惑可能源于 i 字段的定义方式 - 它看起来一旦它被设置为 0 “存在”。实际上,对零的赋值是构造函数的第一行之一(不过,重要的是,在 调用 super() 之后,构造函数通常要求这样做) .

换句话说,您的类(class)完全等同于以下内容:

public class B extends A {

    private int i;

    public B () {
        super();
        i = 0;
        System.out.println(i);
    }

    public void init () {
        i = 1;
    }
}

我想您现在可以明白为什么输出是 0 而不是 1 - 因为对 init() 的调用发生在 字段初始化为0 之前。


出于这个原因和其他原因,总体而言,您应该避免从父类(super class)构造函数调用子类方法 - 因为此时子类甚至还没有初始化,因此很容易违反不变量。 (在未构造的对象上调用方法始终是一个非常糟糕的主意!)这是问题的根本原因,也是您应该寻求解决方案的方向。

出于这个原因,构造函数应该限制自己只调用私有(private)或最终的方法。有关详细信息,请参阅(除其他外):

关于java - 反射不返回正确的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6744567/

相关文章:

java - 序列化的时候能找到 "referring/parent object(s)"吗?

java - Runtime.getRuntime.freeMemory() 未打印正确的值?

java - 将 URL 解析为 ImageIcon 时出现 NullPointerException

java:当字符串参数之一为空时我应该返回什么值."int compareTo(String,String)"

java - ANDROID:MediaPlayer 显示错误 (1, -19)

java - 如何在不同端口上运行的特定 Netty 客户端实例上发送数据

java - 发送和创建文件

java - 同步 Collection 列表

java - 如何在 Java servlet 上下文中获取和设置全局对象

java - 编辑文本的粘贴选项