I'm trying to clean the code of a class that use initialization bloks in a manner I would never do, and I'm just wondering if I am missing some informations. The code looks like this:
#Entity
class MyClass extends BaseClass {
#ManyToMany(fetch=FetchType.EAGER)
private Set<OherClass> others;
{
if (others == null)
others = new HashSet<OtherClass>();
}
public MyClass(){
super();
}
//getters, setters and other stuff follows
}
I think there is no reason to prefer the above code against this:
#Entity
class MyClass extends BaseClass {
#ManyToMany(fetch=FetchType.EAGER)
private Set<OherClass> others = new HashSet<OtherClass>();
}
Or this:
#Entity
class MyClass extends BaseClass {
#ManyToMany(fetch=FetchType.EAGER)
private Set<OherClass> others;
public MyClass(){
this.others = new HashSet<OtherClass>();
}
}
I asked my college, but the only thing he was able to answer is how initialization block works and other things I already know. I wonder if there are some subtle misbehaviour of java (even old one already fixed) or frameworks (hibernate, spring) in case of serialization, reflection, database persistence, injection or any unusual situation that could make that code necessary.
private Set<OherClass> others;
{
if (others == null)
others = new HashSet<OtherClass>();
}
The above code was written without an understanding of Java semantics. others == null will always be true. Therefore this is nothing but a very convoluted and confused way of writing
private Set<OherClass> others = new HashSet<OtherClass>();
Hibernate will indeed wrap some "magic" around the object construction, but it will still need to obtain an instance from the default constructor. At that point all the instance initializers have run.
On a more general note, always prefer to immediately initialize collection-valued variables with constant expressions and, even better, make the field final. That's one less worry for the rest of your code.
With the above you still have all the options open on how to populate the set, which can differ from constructor to constructor.
The only place I see this could be useful, is when the initialization of others needs more than one step and if in the constructor of BaseClass a method is invoked that may be overridden by a sub-class such as MyClass but you want to be sure that others is already properly initialized as it is used by this method. Sounds complicated. I hope that the Java code makes this more clear:
public class BaseClass {
public BaseClass() {
init();
}
public void init() {
// do something...
}
}
public class MyClass extends BaseClass {
private Set<OtherClass> others;
{
others = new HashSet<OtherClass>();
others.add(new OtherClass("hallo"));
// or do more complicated stuff here
}
public MyClass() {
super(); // explicit or may also be implicit
}
#Override
public void init() {
// use initialized others!!
doSomething(this.others);
}
....
}
However, this is a very, very bad pattern and you should never invoke a non-final or non-private method in your constructor as the sub-class may not be properly initialized yet.
Beside that, others is always null if not initialized and you don't have to test this.
Related
I ran into an interesting problem yesterday and while the fix was quite simple, I'm still a bit fuzzy on the "why" of it.
I have a class that has a private member variable that is assigned when it is instantiated, however if it is used in an abstract function that is called by the super class's constructor, the variable does not have a value. The solution to the problem was quite simple, I simply had to declare the variable as static and it was assigned correctly. Some code to illustrate the problem:
class Foo extends BaseClass
{
private final String bar = "fooBar!";
public Foo()
{
super();
}
#Override
public void initialize()
{
System.out.println(bar);
}
}
And the base class:
abstract class BaseClass
{
public BaseClass()
{
initialize();
}
public abstract void initialize();
}
In this example, when we call new Foo(); it will output (null) instead of the expected fooBar!
Since we're instantiated an object of type Foo, should its members not be allocated and assigned prior to calling its (and consequently its super class's) constructor? Is this specified somewhere in the Java language or is it JVM specific?
Thanks for any insight!
The assignment of bar = "fooBar!"; is inlined into the constructor during compile time.
The superclass constructor runs before the subclass constructor, hence it would only be natural that the statement is executed afterwards.
Generally though, it's bad practice to call overridable methods from a constructor.
It is as defined by the Java Language Specification. Changing it to static will almost never be and acceptable solution in real world situation.
See JLS 4.12.5 Initial Values of Variablesand JLS 8.3.2 Initialization of Fields
Overall, it is bad practice to call a non-final method from a constructor. the reason being that it could (and if the method is abstract then definitely does) call method in the class that has not yet been initialized: When new Foo() is executed, the BaseClass initializer (constructor) gets called before the Foo constructor, so Foo.initialize is essentially working on an Object that has not been fully constructed yet.
There's just one thing I would like to add to the accepted answer, because I don't entirely agree with his conclusion.
We've all done this.
class Engine {
public Engine() {
init();
}
void init() {
lockDoors();
releasePressure();
tightenSeatbelts();
launchRocket();
}
...
}
Now the question is, which access modifier should we add to our init() function. Should it be private or protected.
make it private <-- keeps subclasses out
make it protected <-- allows subclasses in
Before you make a choice
Now first of all, you should realize that (almost) all code in the Engine class can be replaced by a subclass.
code in a public function, can easily be overridden
code in a protected function, can easily be overridden
code in a private function, can be replaced by overriding all methods that call it.
Well, there is just one exception:
you can never modify the code of a constructor
you can never avoid a private method being called from the constructor of a super class.
(and of course, you cannot replace a final method)
Protected init() - the wrong way
Let's say the init() method is protected there is indeed a pitfall. It is tempting to override it to add features as follows. That would indeed be a mistake.
class SubEngine extends Engine {
int screws = 5;
void init() {
tightenScrews();
super.init();
}
void tightenScrews() {
// this won't print 5, but it will print 0.
System.out.println("tightening " + screws + " screws");
}
}
Protected init() - the right way
So, basically, you should just disable the parents code and postpone execution to your own constructor instead.
class SubEngine extends Engine {
int screws = 5;
public SubEngine() {
initSubEngine();
}
void init() {
// disable parent code
}
void initSubEngine() {
tightenScrews();
super.init();
}
void tightenScrews() {
// this will print 5 as expected
System.out.println("tightening " + screws + " screws");
}
}
Private init() - you may need a phonecall
Now, what if the init() method is private ?
Like mentioned above, there is no way to disable the code of a parent constructor. And if init() is private you simply cannot disable it.
You'll end up copying the entire Engine class, perhaps just to add 1 line of code.
And that may not be the end of it. Even after copying your class, your copied object won't be an Engine meaning that you won't be able to use your EngineUtil#inspectEngine(Engine engine) function.
Perhaps somebody knew this in advance and made an IEngine interface. Then you can get away with it.
In practice it means you'll have to take your phone, and call to that other department that made the Engine class, and ask them to change their code a little to take away some restrictions.
Intelligent design
There is another way. Constructors are for setting variables. They shouldn't activate anything. Everytime you see a class creating a new Thread from their constructor (or through a private method) that should be a red flag.
class Engine {
public Engine() {
}
public void init() {
lockDoors();
releasePressure();
tightenSeatbelts();
launchRocket();
}
// and you probably also want one of these
public void shutdown() { ... }
...
}
Intention
Of course, your intention may very well be not to open up your code. Perhaps you really don't want to allow others to extend your classes. There certainly can be cases where you want to lock people out.
Be aware that it will also make it harder to write tests for your code.
Anyway that's a different scenario.
I have a method which adds Objects to an static list like this:
#PostConstruct
protected void registerToTransactionList() {
TransactionValidator.registerTransactionList(this);
}
registerTransactionList method just adds "this" to the static list, this method is in BalanceTransactionValidator class which extends TransactionValidator (owner of static list),the problem is all subclasses of BalanceTransactionValidator class are added to static list either,and if I override registerToTransactionList method in them like this:
#Override
#PostConstruct
protected void registerToTransactionList() {
}
It doesn't add subclasses but doesn't add BalanceTransactionValidator either. Can anybody help me on this? Please notice sublasses are overriding this method by default.
make the method private to block the visibility
private void registerToTransactionList() {
}
or make the method final to block it from been override
protected final void registerToTransactionList() {
}
There are two ways of achieving that:
Keep your method as it is; but then you have to actively check for the type of your objects before externally calling that method
Change your whole logic and make that method private
It won't help to make the method final as suggested in one of the comments - your problem is not that subclasses are overwriting that method; in essence, you have a design problem: you wish that subclasses should not invoke that method at all.
So, the only real option that makes sense here is "2.". You see, by having public method on a class that you want to be extended you are implicitly saying: it is perfectly fine to call that method; on any object that is instance of the base class (or child class!).
And in your case, that is not true: you actually do not want that the code behind this method runs for child classes. Then you shouldn't put that method in the list of public/protected methods of your base class!
Finally: you might want to step back and do some reading about good OO design. Class hierarchies do not fall from the sky: you willfully design them for a certain purpose. In other words: there is more to inheritance than just putting some "A extends B" on your class declaration. You have to understand each and every method on your B class; and how your child classes should deal with them!
EDIT: after some more thinking, I guess you are doing things "the wrong way", like:
class BaseClass {
public final void doRegistration() {
BaseClass toRegister = getObjectForRegistration();
if (toRegister != null) { ... register toRegister ...
}
protected BaseClass getObjectForRegistration() {
return null;
}
With that code, you could then put
protected BaseClass getObjectForRegistration() {
if (this instanceof ClassThatShouldBeRegistered) {
return this;
}
return null;
}
into that one class that wants to be registered. Probably there could be even nicer ways of doing so; but after some thinking I don't see how we could avoid the instanceof. But the above code should work; and it only requires specific code only in your base class and in that one class that wants to register something.
I ran into an interesting problem yesterday and while the fix was quite simple, I'm still a bit fuzzy on the "why" of it.
I have a class that has a private member variable that is assigned when it is instantiated, however if it is used in an abstract function that is called by the super class's constructor, the variable does not have a value. The solution to the problem was quite simple, I simply had to declare the variable as static and it was assigned correctly. Some code to illustrate the problem:
class Foo extends BaseClass
{
private final String bar = "fooBar!";
public Foo()
{
super();
}
#Override
public void initialize()
{
System.out.println(bar);
}
}
And the base class:
abstract class BaseClass
{
public BaseClass()
{
initialize();
}
public abstract void initialize();
}
In this example, when we call new Foo(); it will output (null) instead of the expected fooBar!
Since we're instantiated an object of type Foo, should its members not be allocated and assigned prior to calling its (and consequently its super class's) constructor? Is this specified somewhere in the Java language or is it JVM specific?
Thanks for any insight!
The assignment of bar = "fooBar!"; is inlined into the constructor during compile time.
The superclass constructor runs before the subclass constructor, hence it would only be natural that the statement is executed afterwards.
Generally though, it's bad practice to call overridable methods from a constructor.
It is as defined by the Java Language Specification. Changing it to static will almost never be and acceptable solution in real world situation.
See JLS 4.12.5 Initial Values of Variablesand JLS 8.3.2 Initialization of Fields
Overall, it is bad practice to call a non-final method from a constructor. the reason being that it could (and if the method is abstract then definitely does) call method in the class that has not yet been initialized: When new Foo() is executed, the BaseClass initializer (constructor) gets called before the Foo constructor, so Foo.initialize is essentially working on an Object that has not been fully constructed yet.
There's just one thing I would like to add to the accepted answer, because I don't entirely agree with his conclusion.
We've all done this.
class Engine {
public Engine() {
init();
}
void init() {
lockDoors();
releasePressure();
tightenSeatbelts();
launchRocket();
}
...
}
Now the question is, which access modifier should we add to our init() function. Should it be private or protected.
make it private <-- keeps subclasses out
make it protected <-- allows subclasses in
Before you make a choice
Now first of all, you should realize that (almost) all code in the Engine class can be replaced by a subclass.
code in a public function, can easily be overridden
code in a protected function, can easily be overridden
code in a private function, can be replaced by overriding all methods that call it.
Well, there is just one exception:
you can never modify the code of a constructor
you can never avoid a private method being called from the constructor of a super class.
(and of course, you cannot replace a final method)
Protected init() - the wrong way
Let's say the init() method is protected there is indeed a pitfall. It is tempting to override it to add features as follows. That would indeed be a mistake.
class SubEngine extends Engine {
int screws = 5;
void init() {
tightenScrews();
super.init();
}
void tightenScrews() {
// this won't print 5, but it will print 0.
System.out.println("tightening " + screws + " screws");
}
}
Protected init() - the right way
So, basically, you should just disable the parents code and postpone execution to your own constructor instead.
class SubEngine extends Engine {
int screws = 5;
public SubEngine() {
initSubEngine();
}
void init() {
// disable parent code
}
void initSubEngine() {
tightenScrews();
super.init();
}
void tightenScrews() {
// this will print 5 as expected
System.out.println("tightening " + screws + " screws");
}
}
Private init() - you may need a phonecall
Now, what if the init() method is private ?
Like mentioned above, there is no way to disable the code of a parent constructor. And if init() is private you simply cannot disable it.
You'll end up copying the entire Engine class, perhaps just to add 1 line of code.
And that may not be the end of it. Even after copying your class, your copied object won't be an Engine meaning that you won't be able to use your EngineUtil#inspectEngine(Engine engine) function.
Perhaps somebody knew this in advance and made an IEngine interface. Then you can get away with it.
In practice it means you'll have to take your phone, and call to that other department that made the Engine class, and ask them to change their code a little to take away some restrictions.
Intelligent design
There is another way. Constructors are for setting variables. They shouldn't activate anything. Everytime you see a class creating a new Thread from their constructor (or through a private method) that should be a red flag.
class Engine {
public Engine() {
}
public void init() {
lockDoors();
releasePressure();
tightenSeatbelts();
launchRocket();
}
// and you probably also want one of these
public void shutdown() { ... }
...
}
Intention
Of course, your intention may very well be not to open up your code. Perhaps you really don't want to allow others to extend your classes. There certainly can be cases where you want to lock people out.
Be aware that it will also make it harder to write tests for your code.
Anyway that's a different scenario.
Running this piece of code will print null
public class Weird {
static class Collaborator {
private final String someText;
public Collaborator(String text) {
this.someText = text;
}
public String asText() {
return this.someText;
}
}
static class SuperClass {
Collaborator collaborator;
public SuperClass() {
initializeCollaborator();
}
protected void initializeCollaborator() {
this.collaborator = new Collaborator("whatever");
}
public String asText() {
return this.collaborator.asText();
}
}
static class SubClass extends SuperClass {
String someText = "something";
#Override
protected void initializeCollaborator() {
this.collaborator = new Collaborator(this.someText);
}
}
public static void main(String[] arguments) {
System.out.println(new Weird.SubClass().asText());
}
}
(Here is also the GitHub Gist)
Now, I know why this happens (it's because the field of the superclass is initialized and then the constructor of the superclass is called, before the field of the subclass is initialized)
The questions are:
What is the design issue here? What is wrong with this design, from an OOP point of view, so that the result looks weird to a programmer? What OOP principles are being broken through this design?
How to refactor so it does not work 'weird' and is proper OOP code?
What's wrong with the design: you're calling an instance method from a constructor, and then overriding it in a subclass. Don't do that. Ideally, only call private or final instance methods, or static methods, from constructor bodies. You're also exposing a field (which is an implementation detail) outside SuperClass, which isn't a great idea - but writing a protected setCollaborator method and calling that from initializeCollaborator would give the same problem.
As to how to fix it - it's not really clear what you're trying to achieve. Why do you need the initializeCollaborator method at all? There can be various ways of approaching this problem, but they really depend on knowing eaxctly what you're trying to achieve. (Heck, in some cases the best solution is not to use inheritance in the first place. Prefer composition over inheritance, and all that :)
My issue with the design is the someText string should either be an explicit dependency (or "collaborator") of the Collaborator object, or of SubClass, or explicitly a part of the global context (so a constant or a property of a shared context object).
Ideally, either Collaborator should be responsible for retrieving its dependencies; or, if SubClass is responsible for this, it should have someText as a dependency (even if it's always initialised to the same value), and only initialise Collaborator when someText is set.
Conceptually speaking, the dependency relation between objects in the design imposes a partial ordering of the initialisation. The mechanism to implement this ordering should always be explicit in your design, instead of relying on implementation details of the Java language.
An (overengineered) example:
interface ICollaboratorTextLocator {
String getCollaboratorText();
}
class ConstantCollaboratorTextLocator implements ICollaboratorTextLocator {
String text;
ConstantCollaboratorTextLocator(String text) {
this.text = text;
}
}
class SuperClass {
Collaborator collaborator;
public setCollaboratorTextLocator(ICollaboratorTextLocator locator) {
collaborator = new Collaborator(locator.getCollaboratorText());
}
SuperClass() {
setCollaboratorTextLocator(new ConstantCollaboratorTextLocator("whatever"));
}
}
class SubClass {
String text = "something";
SubClass() {
setCollaboratorTextLocator(new ConstantCollaboratorTextLocator(text));
}
}
(Now excuse me, I need to go stand under a waterfall after writing something called ConstantCollaboratorTextLocator.)
Instead of using the intializeCollaborator method, make the Collaborator a parameter on the constructor and call it using super(new Collaborator(..)) from the child.
The default way to implement singleton pattern is:
class MyClass {
private static MyClass instance;
public static MyClass getInstance() {
if (instance == null) {
instance = new MyClass();
}
return instance;
}
}
In an old project, I've tried to simplify the things writing:
class MyClass {
private static final MyClass instance = new MyClass();
public static MyClass getInstance() {
return instance;
}
}
But it sometimes fail. I just never knew why, and I did the default way.
Making a SSCCE to post here today, I've realized the code works.
So, I would like to know opinions..
Is this a aleatory fail code?
Is there any chance of the second approach return null?
Am I going crazy?
--
Although I don't know if is the right answer for every case, it's a really interesting answer by #Alfred:
I also would like to point out that singletons are testing nightmare and that according to the big guys you should use google's dependency injection framework.
The recommended (by Effective Java 2nd ed) way is to do the "enum singleton pattern":
enum MyClass {
INSTANCE;
// rest of singleton goes here
}
The key insight here is that enum values are single-instance, just like singleton. So, by making a one-value enum, you have just made yourself a singleton. The beauty of this approach is that it's completely thread-safe, and it's also safe against any kinds of loopholes that would allow people to create other instances.
The first solution is (I believe) not thread-safe.
The second solution is (I believe) thread-safe, but might not work if you have complicated initialization dependencies in which MyClass.getInstance() is called before the MyClass static initializations are completed. That's probably the problem you were seeing.
Both solutions allow someone to create another instance of your (notionally) singleton class.
A more robust solution is:
class MyClass {
private static MyClass instance;
private MyClass() { }
public synchronized static MyClass getInstance() {
if (instance == null) {
instance = new MyClass();
}
return instance;
}
}
In a modern JVM, the cost of acquiring a lock is miniscule, provided that there is no contention over the lock.
EDIT #Nate questions my statement about static initialization order possibly causing problems. Consider the following (pathological) example:
public ClassA {
public static ClassB myB = ClassB.getInstance();
public static ClassA me = new ClassA();
public static ClassA getInstance() {
return me;
}
}
public ClassB {
public static ClassA myA = ClassA.getInstance();
public static ClassB me = new ClassB();
public static ClassB getInstance() {
return me;
}
}
There are two possible initialization orders for these two classes. Both result in a static method being called before the method's classes static initialization has been performed. This will result in either ClassA.myB or ClassB.myA being initialized to null.
In practice, cyclic dependencies between statics are less obvious than this. But the fact remains that if there is a cyclic dependency: 1) the Java compiler won't be able to tell you about it, 2) the JVM will not tell you about it. Rather, the JVM will silently pick an initialization order without "understanding" the semantics of what you are trying to do ... possibly resulting in something unexpected / wrong.
EDIT 2 - This is described in the JLS 12.4.1 as follows:
As shown in an example in §8.3.2.3, the fact that initialization code is unrestricted allows examples to be constructed where the value of a class variable can be observed when it still has its initial default value, before its initializing expression is evaluated, but such examples are rare in practice. (Such examples can be also constructed for instance variable initialization; see the example at the end of §12.5). The full power of the language is available in these initializers; programmers must exercise some care. ...
The second example is preferable, since the first isn't thread safe (as pointed out in the comments). The first example uses a technique called lazy instantiation (or lazy initialization), which ensures that the Singleton instance isn't created unless it's actually needed. This isn't really necessary in Java because of the way Java handles class loading and static instance variable initialization.
I also would like to point out that singletons are testing nightmare and that according to the big guys you should use google's dependency injection framework.
Remember, you need to declare a private constructor to ensure the singleton property.
The second case could be even simpler with just
class MyClass {
public static final MyClass instance = new MyClass();
private MyClass() {
super()
}
}
`
As others have noted, the first is not thread-safe. Don't bother with it as the second is perfectly fine, and will instantiate the object only when MyClass is referenced. Further it makes the reference final which expresses the intent better.
Just make sure that the declaration
private static final MyClass INSTANCE = new MyClass();
is the first static declaration in your class to avoid risk of calls to getInstance() or INSTANCE before it is initialized.
Don't forget the SingletonHolder pattern. See this SO question.
I don't know the answers to your questions, but here is how I might structure the same thing.
class MyClass {
private static MyClass instance;
static {
instance = new MyClass();
}
private MyClass() { }
public static MyClass getInstance() {
return instance;
}
}