English 中文(简体)
将其用作构造函数中方法调用的参数
原标题:
  • 时间:2008-09-24 13:42:47
  •  标签:

我有一个构造函数,如下所示:

public Agent(){

    this.name = "John";
    this.id = 9;
    this.setTopWorldAgent(this, "Top_World_Agent", true);

}

在方法调用中,我得到了一个空指针异常。这似乎是因为我在setTopWorldAgent方法中使用了这个参数。通过删除此方法调用,一切看起来都很好。为什么会发生这种情况?其他人经历过这种情况吗?

最佳回答

您可以将其传递给方法,但setTopWorldAgent()不能是抽象的。不能在构造函数中进行虚拟调用

在对象的构造函数中,可以调用该对象或基类中定义的方法,但不能期望调用派生类提供的东西,因为派生类的某些部分尚未构造。如果setTopWorldAgent()是抽象的,我会预料到某种编译器错误

在Java中,您可以通过构造函数和派生类获得令人惊讶的行为——这里有一个例子

http://en.wikipedia.org/wiki/Virtual_functions#Java_3

如果你习惯了C#或C++,你可能会认为调用虚拟函数而不是调用重写函数是安全的。在Java中,即使派生类没有完全构造好,也会进行虚拟调用。

如果不是这样,那么大概setTopWorldAgent()需要的所有部分都被初始化了——如果不是,它可能是需要初始化的成员之一。

编辑:以为这是C#

问题回答

出于好奇,为什么要将其传递给同一类的成员函数?setTopWorldAgent()可以直接使用它。它看起来不像你的构造函数或setTopWorldAgent()是静态的,所以我不确定你为什么要传递一个成员函数——它已经可以访问的东西。

除非我错过了什么。。。

为什么setTopWorldAgent需要这个作为参数?基于调用,它是一个实例方法,因此它可以引用this,而无需将其作为参数接收。

“this”永远不应该为null。你确定是因为这个原因引发了异常吗?

需要注意的是,如果方法是虚拟的,或者调用任何虚拟方法,那么属于子类的方法可能会在初始化子类的变量之前运行。

我认为更重要的是,你到底为什么要把它作为一个参数传递给这个方法?

以下内容将测试你所说的发生在你身上的事情,我对此没有任何问题。

public class Test {
  public Test() {
    this.hi(this);
  }
  public void hi(Test t) {
    System.out.println(t);
  }

  public static void main(String[] args) throws Exception {
    Test t = new Test();
  }
}

既然setTopWorldAgent看起来是一个实例方法,那么你为什么要把它传递给它呢?

错误必须在其他地方,因为上面的代码肯定有效,空引用必须是其他地方。

如果您的代理正在实施ITopWorldAgent,那么您实际上应该这样做:


Agent agent = new Agent("John", 9);
agent.setTopWorldAgent(agent, "Top_World_Agent", true);

如果不是,那么你为什么要以你现在的方式设置一些东西呢?

我认为setTopWorldAgent方法中的某些内容使用了一个尚未在构造函数中初始化的值。

<code>这个</code>不是null,这是肯定的。已经分配了。

也就是说,不需要将this传递到方法中,它在所有实例方法中都自动可用。如果该方法是静态的,那么您可能需要将其重构为实例方法。

Java的规则规定,永远不应该将它从构造函数传递给另一个方法,原因很简单,就是对象还没有完全构造好。它引用的对象可能处于不一致的状态。我很惊讶实际的this引用是null,但当它被传递给setTopWorldAgent时,它的一些成员是null,并且该方法因此引发异常,这一点也不奇怪。

通常,只要您没有实际访问任何成员或调用方法(例如,如果您想在另一个对象中设置对此的引用),就可以从构造函数传递此信息。

当然,在这种情况下,参数是不必要的,因为该方法已经引用了它。

很高兴你得到了答案。我想补充一点,将其作为参数传递可能会导致意外的并发问题。基本上,您提供了对象的状态被潜在的非线程安全代码不安全地操纵的可能性。





相关问题
热门标签