提问人: 提问时间:9/24/2008 更新时间:9/25/2008 访问量:10240
在构造函数中使用“this”作为方法调用的参数
Using 'this' as a parameter to a method call in a constructor
问:
我有一个构造函数,如下所示:
public Agent(){
this.name = "John";
this.id = 9;
this.setTopWorldAgent(this, "Top_World_Agent", true);
}
我在方法调用中收到一个空指针异常。这似乎是因为我在 setTopWorldAgent 方法中使用“this”作为参数。通过删除此方法调用,一切看起来都很好。为什么会这样?还有其他人经历过吗?
答:
this
不是空的,这一点是肯定的。它已被分配。
也就是说,无需传入方法,它在所有实例方法中都自动可用。如果该方法是静态的,则可能需要将其重构为实例方法。this
你可以把它传递给方法,但setTopWorldAgent()不能是抽象的。不能在构造函数中进行虚拟调用。
在对象的构造函数中,可以调用该对象或基类中定义的方法,但不能指望调用派生类将提供的内容,因为派生类的某些部分尚未构造。如果setTopWorldAgent()是抽象的,我本来会预料到某种编译器错误。
在 Java 中,你可以通过构造函数和派生类获得令人惊讶的行为——下面是一个例子
http://en.wikipedia.org/wiki/Virtual_functions#Java_3
如果您习惯使用 C# 或 C++,您可能会认为调用虚拟函数而不是调用重写的函数是安全的。在 Java 中,即使派生类未完全构造,也会进行虚拟调用。
如果这不是正在发生的事情,那么据推测,setTopWorldAgent() 需要的所有部分都已初始化 - 如果不是,则可能是需要初始化的成员之一。
编辑:以为这是C#
评论
“this”绝不应为 null。您确定因此而引发异常吗?
需要注意的是,如果方法是虚拟的,或者调用任何虚拟方法,那么在初始化子类的变量之前,可能会运行属于子类的方法。
评论
错误一定在其他地方,因为上面的代码肯定有效,空引用必须是其他东西。
为什么需要作为论据?根据调用,它是一个实例方法,因此它可以引用,而无需将其作为参数接收。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 时为 null,并且该方法因此抛出异常。
通常,只要您实际上不访问任何成员或调用方法,例如,如果您想在另一个对象中设置对“this”的引用,就可以从构造函数传递“this”。
当然,在这种情况下,参数是不必要的,因为该方法已经引用了“this”。
很高兴你得到了答案。我想补充一点,将“this”作为参数传递可能会导致意外的并发问题。基本上,您提供了对象状态被潜在的非线程安全代码不安全地操纵的可能性。
上一个:jQuery 多个单选按钮
评论