I need this because the constructor in the superclass is calling a method which is overridden in the subclass. The method returns a value which is passed to the subclass' constructor. But the superclass constructor must be called before the subclass constructor, so I have no chance to save the value passed in.
相关问题
- Delete Messages from a Topic in Apache Kafka
- how to define constructor for Python's new Nam
- Jackson Deserialization not calling deserialize on
- How to maintain order of key-value in DataFrame sa
- StackExchange API - Deserialize Date in JSON Respo
If this is a problem you have a fundamental problem in your class hierarchy; superclasses cannot know about any specific subclass because there might be several, they might even be loaded dynamically at runtime. That is why any super() calls in a constructor must be on the first line.
As a general rule, don't call any public methods in a constructor.
I know the problem. It is not possible. If the super class is not your own and you have no other options then you can do some bad hacks. But it is not recommended.
Solution 1:
Use a static factory with a synchronized. This can look like (redudced):
Solution 2:
Make a differentiation in your method if the own constructor was already run with a flag. Then you need to duplicate some stuff of the super constructor with the real value.
You didn't mention whether you can modify the superclass's constructor at all. If you can, then this is doable. As other have said, this is not advisable, but here's a contrived example that does what you're looking for--the superclass calls an overridden method which uses an argument that was passed to the subclass's constructor:
> java Derived
25
Calling an overridden method from the superclass constructor is simply not going to work - don't do it. The superclass constructor must always finish before that of the subclass. While the superclass constructor is executing, the object in question is a (half initialized) instance of the superclass, not the subclass! So if you try to call any overridden function from the constructor, the subclass fields it may depend on are not yet initialized (just as you have observed). This is a fundamental fact of class design, and there is no workaround.
As explained in Effective Java 2nd. Ed. (Chapter 4, Item 17):
If you can change the superclass implementation, try moving the call to the virtual function out of the constructor. One way to achieve this is using a Factory Method:
Note that the constructor of
Subclass
is private to ensure that it can only be instantiated viacreateInstance()
, thus instances are always initialized properly. OTOH this also prevents further subclassing. However, subclassing a concrete class is not recommended anyway - a class meant to be subclassed should be abstract (with aprotected
constructor in this case). And of course, any further subclasses must also have non-public constructors and static factory methods which diligently callinit()
...Your question is summarized by the following snippet:
This is a quote from Josh Bloch and Neal Gafter's Java Puzzlers: Traps, Pitfalls, and Corner Cases:
In short: DON'T DO IT!
Moreover, the book proposes a possible solution (slightly edited for generality):