Java 从构造函数调用方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18138397/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Calling method from constructor
提问by StrangeWill
Excuse any minor syntax errors or whatnot, I'm experiencing this with a Jitsi module and not being super familiar with Java want to confirm what is going on and why and how it should be fixed.
请原谅任何轻微的语法错误或诸如此类的东西,我正在使用 Jitsi 模块遇到此问题,并且对 Java 不太熟悉,想确认发生了什么以及为什么以及应该如何修复它。
public abstract class A
{
public A()
{
this.load();
}
protected void load()
{
}
}
public class B extends A
{
private String testString = null;
public B()
{
super();
}
@Override
protected void load()
{
testString = "test";
}
}
The application is doing this when creating an instance of the class B using a load class by name method:
应用程序在使用按名称加载类的方法创建类 B 的实例时执行此操作:
- Calls overridden load() in class B
- Initializes variables (calls "private string testString = null" according to debugger), nulling them out.
- 在 B 类中调用覆盖的 load()
- 初始化变量(根据调试器调用“私有字符串 testString = null”),将它们归零。
Is this expected Java behavior? What could cause this? It's a Java 1.6 application running on the 1.7 JDK.
这是预期的 Java 行为吗?什么可能导致这种情况?它是在 1.7 JDK 上运行的 Java 1.6 应用程序。
采纳答案by Rohit Jain
Is this expected Java behavior?
这是预期的 Java 行为吗?
Yes.
是的。
What could cause this?
什么可能导致这种情况?
Your invocation of non-final overridden method in non-final super class constructor.
您在非最终超类构造函数中调用非最终覆盖的方法。
Let's see what happens step-by-step:
让我们一步一步地看看会发生什么:
- You create an instance of
B
. B()
calls super class constructor -A()
, to initialize the super class members.A()
now invokes a non-final method which is overridden inB
class, as a part of initialization.- Since the instance in the context is of
B
class, the methodload()
invoked is ofB
class. load()
initializes theB
class instance field -testString
.- The super class constructor finishes job, and returns (Assuming chaining of constructor till
Object
class have been finished) - The
B()
constructor starts executing further, initializing it's own member. - Now, as a part of initilization process,
B
overwrites the previous written value intestString
, and re-initializes it tonull
.
- 您创建了一个
B
. B()
调用超类构造函数 -A()
来初始化超类成员。A()
现在调用一个在B
类中被覆盖的非最终方法,作为初始化的一部分。- 由于上下文中的实例属于
B
类,因此load()
调用的方法属于B
类。 load()
初始化B
类实例字段 -testString
。- 超类构造函数完成工作并返回(假设构造函数链接到
Object
类完成) - 该
B()
构造函数开始执行进一步,初始化它自己的成员。 - 现在,作为初始化过程的一部分,
B
覆盖 中先前写入的值testString
,并将其重新初始化为null
。
Moral:Never call a non-final public method of a non-final class in it's constructor.
道德:永远不要在构造函数中调用非 final 类的非 final 公共方法。
回答by Thomas W
This is a common problem-pattern with initialization-on-construction, and can frequently be found in infrastructure code & home-made DAOs.
这是构建时初始化的常见问题模式,经常可以在基础设施代码和自制 DAO 中找到。
The assignment to 'null' is unneeded & can be removed.
不需要分配给 'null' 并且可以删除。
If that's not enough as a quick patch, then: Move all the post-construction init to a separate method, and wrap it all in a "static method" pseudo-constructor.
如果这还不足以作为一个快速补丁,那么: 将所有构建后的 init 移动到一个单独的方法中,并将其全部包装在一个“静态方法”伪构造函数中。
And if you're doing DAO stuff, it's really good to distinguish between "load" and "create", since these are completely different instantiations. Define separate "static constructor" methods & perhaps separate internal inits, for these.
如果你正在做 DAO 的事情,区分“加载”和“创建”真的很好,因为它们是完全不同的实例化。为这些定义单独的“静态构造函数”方法和可能单独的内部初始化。
abstract public class A {
protected void initAfterCreate() {}
}
public class B {
@Override
protected void initAfterCreate() {
this.testString = "test";
}
// static constructors;
// --
static public B createB() {
B result = new B();
result.initAfterCreate();
}
}
Demonstrating load/createseparation for a DAO:
演示DAO 的加载/创建分离:
public class Order {
protected int id;
protected boolean dbExists;
static public load (int id) {
Order result = new Order( id, true);
// populate from SQL query..
return result;
}
static public create() {
// allocate a key.
int id = KeyAlloc.allocate( "Order");
Order result = new Order( id, false);
}
// internal constructor; not for external access.
//
protected Order (int id, boolean dbExists) {
this.id = id;
this.dbExists = dbExists;
}
}