【问题标题】:Using 'this' as a parameter to a method call in a constructor在构造函数中使用“this”作为方法调用的参数
【发布时间】:2010-09-12 17:39:13
【问题描述】:

我有一个如下构造函数:

public Agent(){

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

}

我在方法调用中遇到空指针异常。这似乎是因为我在 setTopWorldAgent 方法中使用“this”作为参数。通过删除此方法调用,一切看起来都很好。为什么会这样?有其他人经历过吗?

【问题讨论】:

  • 我猜 setTopWorldAgent 中的代码是发生异常的地方。也许您可以添加异常的堆栈跟踪和该方法的代码。
  • 我想看看提问者的最终解决方案是什么。
  • 这叫自变量,不是参数。

标签: java constructor methods call this


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    Java 的规则规定,您永远不应该将“this”从其构造函数传递给另一个方法,原因很简单,因为对象尚未完全构造。它引用的对象可能处于不一致的状态。我对实际的“this”引用为空感到惊讶,但对于“this”的某些成员在传递给 setTopWorldAgent 时为空,并且该方法因此引发异常,这一点一点也不奇怪。

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

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

    【讨论】:

      【解决方案3】:

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

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

      在 Java 中,构造函数和派生类会出现令人惊讶的行为 -- 这是一个示例

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

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

      如果这不是正在发生的事情,那么大概是 setTopWorldAgent() 需要的 this 的所有部分都已初始化 - 如果不是,它可能是需要初始化的 this 的成员之一。

      编辑:认为这是 C#

      【讨论】:

      • 但是即使你做了函数调用不会失败!
      • 这个答案显然是不正确的。即使该类是抽象的并且方法 setTopWorldAgent 也是抽象的,此时的创建也会使 this 不为空。它很容易用一个测试用例来展示。
      • 该死的,你们为什么不赞成这个答案?没错!
      • 在Java中,你可以调用一个抽象方法,它会被解析为子类中的实现方法。但是您是正确的,子类变量不会被初始化。父类构造函数在子类之前调用​​。
      • 感谢康拉德!这不是空的——还有别的东西。我是在建议一些可能为 null 的东西,或者你可能会被愚弄以为某些东西被调用而实际上没有被调用的方式。
      【解决方案4】:

      this 不为空,这是肯定的。已分配。

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

      【讨论】:

        【解决方案5】:

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

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

        如果不是,那你为什么要这样设置?

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

        【讨论】:

          【解决方案6】:

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

          除非我错过了什么......

          【讨论】:

            【解决方案7】:

            鉴于 setTopWorldAgent 似乎是一个实例方法,你为什么还要将它传递给它?

            【讨论】:

              【解决方案8】:

              我想得更清楚了,你到底为什么要将“this”作为参数传递给“this”中的方法?

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

              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();
                }
              }
              

              【讨论】:

                【解决方案9】:

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

                【讨论】:

                  【解决方案10】:

                  错误一定在其他地方,因为上面的代码肯定可以工作,空引用必须是其他地方。

                  【讨论】:

                    【解决方案11】:

                    “this”永远不应该为空。您确定因此引发了异常吗?

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

                    【讨论】:

                    • 在 Java 中,您可以在构造函数中调用抽象方法。子类中的实现方法会被调用。
                    猜你喜欢
                    • 2014-05-09
                    • 1970-01-01
                    • 2016-03-10
                    • 2011-04-11
                    • 2017-05-26
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2018-04-26
                    相关资源
                    最近更新 更多