使用" this"作为构造函数中方法调用的参数
我有一个如下的构造函数:
public Agent(){ this.name = "John"; this.id = 9; this.setTopWorldAgent(this, "Top_World_Agent", true); }
我在方法调用中收到一个空指针异常。似乎是因为我在setTopWorldAgent方法中使用" this"作为参数。通过删除此方法调用,一切看起来都很好。为什么会这样?还有其他人经历过吗?
解决方案
" this"不为null,可以肯定。已分配。
就是说,不需要将" this"传递到方法中,它在所有实例方法中都自动可用。如果该方法是静态的,则可能需要将其重构为实例方法。
我们可以将其传递给方法,但是setTopWorldAgent()不能是抽象的。我们不能在构造函数中进行虚拟调用。
在对象的构造函数中,可以调用在该对象或者基类中定义的方法,但是不能期望调用派生类将提供的某些方法,因为尚未构造派生类的某些部分。如果setTopWorldAgent()是抽象的,我可能会想到某种编译器错误。
在Java中,我们可以通过构造函数和派生类获得令人惊讶的行为-这是一个示例
http://en.wikipedia.org/wiki/Virtual_functions#Java_3
如果我们习惯使用Cor C ++,则可能会认为调用虚拟函数而不调用覆盖的函数是安全的。在Java中,即使未完全构造派生类,也会进行虚拟调用。
如果这不是正在发生的事情,那么大概setTopWorldAgent()需要的所有部分都已初始化-如果不是,则可能是其中需要初始化的成员之一。
编辑:以为这是C#
" this"绝不能为空。我们确定是因为这个原因引发了异常吗?
要注意的是,如果该方法是虚拟的,或者调用任何虚拟方法,那么在初始化子类的变量之前,可能会运行属于子类的方法。
该错误必须在其他地方,因为上面的代码确实有效,空引用必须是其他地方。
为什么" setTopWorldAgent"需要" this"作为参数?基于调用,它是一个实例方法,因此它可以引用this
而不需要将其作为参数接收。
我认为更重要的是,到底为什么我们要将" 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(); } }
鉴于setTopWorldAgent似乎是一个实例方法,我们为什么无论如何都要通过它呢?
出于好奇,为什么将" this"传递给同一类的成员函数? setTopWorldAgent()可以直接使用" this"。它看起来不像构造函数或者setTopWorldAgent()是静态的,所以我不确定为什么我们要传递一个已经可以访问的成员函数。
除非我错过了什么...
如果代理正在实现ITopWorldAgent,那么我们实际上应该这样做:
Agent agent = new Agent("John", 9); agent.setTopWorldAgent(agent, "Top_World_Agent", true);
如果不是,那为什么要按自己的方式设置某些东西?
我假设setTopWorldAgent方法中的某些东西正在使用尚未在构造函数中初始化的值。
Java规则规定,永远不要将" this"传递给其构造函数中的另一个方法,原因很简单,即对象尚未完全构造。它引用的对象可能处于不一致状态。我对实际的" this"引用为null感到惊讶,但对于" this"的某些成员传递给setTopWorldAgent时,它一点也不感到惊讶,并且该方法因此抛出异常。
通常,只要我们实际上不访问任何成员或者调用方法(例如,如果我们想在另一个对象中设置对" this"的引用),就可以避免从构造函数传递" this"。
在这种情况下,当然不需要参数,因为该方法已经引用了" this"。
很高兴我们得到了答案。我想补充一点,将" this"作为参数传递可能会导致意外的并发问题。基本上,我们提供了可能由潜在的非线程安全代码不安全地操纵对象状态的可能性。