I'm new to Java but experienced in C++. I came across some code that I didn't understand:
public class SomeClass {
private SomeOtherClass someOther = new SomeOtherClass();
private AThirdClass thirdClass;
SomeClass() {
this.thirdClass = new AThirdClass();
}
}
Why when there is only a single constructor would you have someOther initialized in the initialization and thirdClass initialized in the constructor?
The below is one reason you may wish to do that.
public class SomeClass {
private SomeOtherClass someOther = new SomeOtherClass();
private AThirdClass thirdClass;
SomeClass( int x ) {
this.thirdClass = new AThirdClass( x );
}
}
But that only explains why you would want to initialize thirdClass in the constructor. I am at a loss to explain why you would want to initialize someOther in the init block.
There is absolutely no reason, unless you get into static declarations, in which case it could make some sense.
There's nothing in your example that would suggest a reason, but underlying implementations may have problematic and poorly-considered code to consider. It may be important for you to know that the initialization of SomeOtherClass in your example will always run before the initialization in the constructor. Someone may have thought that was important.
Or, it could simply be two different developers with two different style preferences. Neither is technically wrong, but both have their (dis)advantages.
Related
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.
So I did read the tread of what and when static initalizer is executed from this thread. Static initializer in Java. But I am running into some old code written by someone else and can't seem to understand why he would use it the way he did.
My Class:
public class ClassA extends Thread {
.... private vars ....
private static Config config;
static {
config = null;
}
public ClassA(Config config) {
ClassA.config = config;
}
}
Why didn't he just do this?
public class ClassA extends Thread {
.... private vars ....
private static Config config = null;
public ClassA(Config config) {
ClassA.config = config;
}
}
I understand that static initalizer gets call as the class being redenered, so it sets config => null, while if i don't use static initalizer, instance variables get initalizer right before the constructor, and right after super. So wouldn't the two class be doing the same thing?
These classes are doing the same thing, but more complex static initializers can't always be done on a single line.
The static initializer in your first example won't have any effect on the behavior of that class. You could remove it entirely and nothing would change.
Why did I write x = x + 1 instead of x++ ? No particular reason, I just did it that way. I think it's the same here, because the 2 are basically identical and it doesn't really matter. On the other hand, if more complicated initialization is desired sometime in the future, maybe he can't do that in that single line of code.
The static block will initialize config only once when class is loaded, no matter how many instances of ClassA there are.
It doesn't matter which solution, it's just a technicality, I've seen people use both.
Both are doing exactly the same thing, It a matter of design choice.
I was wondering, whether the following code are safe.
public class GUIBundle {
// The technique known as the initialization on demand holder idiom,
// is as lazy as possible.
// http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom
//private static class BundleHolder {
// private static final ResourceBundle bundle = ResourceBundle.getBundle("org.yccheok.jstock.data.gui");
//}
private static final ResourceBundle bundle = ResourceBundle.getBundle("org.yccheok.jstock.data.gui");
private GUIBundle() {
}
public static String getString(String key) {
// return BundleHolder.bundle.getString(key);
return bundle.getString(key);
}
}
public class SellPortfolioChartJDialog extends javax.swing.JDialog {
private static final String[] cNames = new String[] {
GUIBundle.getString("BuyPortfolioTreeTableModel_NetGainValue")
};
}
Since cNames is within static scope, is it safe for it to access static bundle? Does it make any different whether I am using lazy initialization technique?
I remember I came across an article (I lost the article anyway) talking about nondeterministic of initialization order of static variables. I am not sure whether the nondeterministic of initialization order of static variables, applied to the above case?
I believe the nondeterministic initialization order of static variables (in different compilation units) is a C/C++ "feature". In Java, static variables are initialized when their class is loaded, and within a single class in their order of declaration. So the order is deterministic (at least in a single threaded environment).
This guarantees that what you intend to do should work: when GUIBundle is first referenced, the classloader loads it and initializes bundle too. The call to GUIBundle.getString() happens only after the class initialization is done.
That works just fine. I got it to compile by keeping the principle the same but using different classes (I didn't want to bother getting your jars... :-).
Obviously there are some small problems, like how you declare your String[] needs to be
private static final String[] cNames = new String[] {
GUIBundle.getString("BuyPortfolioTreeTableModel_NetGainValue")
};
}
Other than that, it works just fine. The key to using statics in other statics is the order they're declared. You can't do this
static Foo b = a;
static Foo a = new Foo();
I think its perfectly safe, You see because the when
GUIBundle.getString
is used in your JDialog subclass, the JVM will completely initialize (see java language spec loading, linking and initialization) the class GUIBundle before calling the method getString on it, which will initialize all the class (static) initializers in the class GUIBundle.
Edit: Read more about this in VM spec:
http://java.sun.com/docs/books/jvms/second_edition/html/Concepts.doc.html#16491
To me it's safe.
bundle is initialized right after GUIBuilder is loaded and therfore before getString is called for the first time.
I have a Set class (This is J2ME, so I have limited access to the standard API; just to explain my apparent wheel-reinvention). I am using my set class to create constant sets of things in classes and subclasses. It sort of looks like this...
class ParentClass
{
protected final static Set THE_SET = new Set() {{
add("one");
add("two");
add("three");
}};
}
class SubClass extends ParentClass
{
protected final static Set THE_SET = new Set() {{
add("four");
add("five");
add("six");
union(ParentClass.THE_SET); /* [1] */
}};
}
All looks fine, except the line at [1] causes a null pointer exception. Presumably this means that the static initialiser in the subclass is being run before that of the parent class. This surprised me because I'd have thought it would run the static blocks in any new imports first, before running any in the instatiated subclass.
Am I right in this assumption? Is there any way to control or work around this behaviour?
Update:
Things are even stranger. I tried this instead (Note the 'new ParentClass()' line):
class ParentClass
{
public ParentClass()
{
System.out.println(THE_SET);
}
protected final static Set THE_SET = new Set() {{
add("one");
add("two");
add("three");
}};
}
class SubClass extends ParentClass
{
protected final static Set THE_SET = new Set() {{
System.out.println("a");
new ParentClass();
System.out.println("b");
add("four");
System.out.println("c");
add("five");
System.out.println("d");
add("six");
System.out.println("e");
union(ParentClass.THE_SET); /* [1] */
System.out.println("f");
}};
}
And the output is strange:
a
["one", "two", "three"]
b
c
d
e
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.NullPointerException
So ParentClass is initialised, but the subclass doesn't have access to it in its static initializer.
Is this what you are trying to accomplish? Or do you need a local implementation of the Set interface?
class ParentClass
{
protected final static Set THE_SET;
static {
THE_SET = new HashSet();
THE_SET.add("one");
THE_SET.add("two");
THE_SET.add("three");
}
}
class SubClass extends ParentClass
{
protected final static Set THE_SECOND_SET;
static {
THE_SECOND_SET = new HashSet();
THE_SECOND_SET.add("four");
THE_SECOND_SET.add("five");
THE_SECOND_SET.add("six");
union(ParentClass.THE_SET); /* [1] */
}
}
There is no guarantee for static initializer order among classes. Within a class, they run in the order of the source code.
If you think about it, therre really couldn't be an order among classes, because you don't control when the classes are loaded either; you might dynamically load a class, or the JVM might optimize the load order.
Even if you didn't have the extends ParentClass in there, using ParentClass should cause it to become initialised.
Where things become tricky is when you have cycles. With a cycle it is possible to access a class before it has been fully initialised. As Java is a multithreaded system, you can also have problems with deadlocks and races.
May be your Java ME implementation is buggy (not unheard of). Part your full ParentClass references your ChildClass. Or perhaps there is some other application/library bug.
On a related note, if you don't -target 1.4 or later, inner classes' outer this is not initialised as soon as you might expect. As presented your code uses (technically) inner classes in a static context, so that shouldn't be a problem.
Also it's interesting to point out that static initialisation is slightly confused in situations like this, because you actually have four classes there.
Simply stop abusing the concept of anonymous classes for instance initialization (the so-called "double brace idiom").
Given the output line of ["one", "two", "three"], it is basically impossible that ParentClass.THE_SET has never been initialized.
Of course, it is possible that there isn't only one classloader involved, but it would certainly be helpful to see the method and line number where the null pointer happens.
I think something similar was written in Java puzzles book or google's YouTube video about java tricks.
I see this idiom of initializing instance variables quite a bit
public class Test{
private Long l = 1l;
private MyClass mc = new MyClass();
public Test(){}
...
}
But I would prefer
public class Test{
private Long l;
private MyClass mc;
public Test(){
l = 1l;
mc = new MyClass();
}
...
}
Considering that these are non-final variables, are the 2 approaches equivalent or is one "more" correct than the other in terms of thread safety?
Thread safety isn't an issue because this happens at construction phase, and two threads cannot be constructing the same object. Well, if you let this escape from the constructor, it might be possible for another thread to access the object during construction, but you really shouldn't do that. Functionality-wise, the two options are the same, so even if there were thread-safety issues, they would affect both the same way.
The first option, of initializing the fields at their declaration, is not always possible if you need to do some computation that cannot be done in an initializer (even then, you can keep the initialization out of the constructor if you do it in an initializer block, though). But if either way is possible, then it's purely a style issue, and I don't think there is a clear preference among Java programmers, so go with whichever seems better to you.
since your variables are instance variables, not class variables, you don't have a thread safety issue during initialization using either method. I'm sure others will chime in if there's a Java-standard-recommended best practice.
I think it's the matter of personal preference and your project coding standards.
Just make sure you only initialize variables in one place ( either constructor, or inline ).
Having initialization work done in the constructor gives you a better place for exception handling.
They are both not thread-safe. If thread A constructs the object, then thread B may or may not observer an incompletely initialized Test object or MyClass object. The visibility guarantees after a constructor exits only apply to final fields.
See http://pveentjer.wordpress.com/2007/03/18/immutability-doesnt-guarantee-thread-safety/
In terms of thread safety, they are equivalent. Both will need to execute the same instructions, and if you prefer the second (which I agree with you in your preference) then I would use that. If you want thread safety around a constructor, you would need a synchronized call around the constructor call.
I am not sure if this was answered earlier. But, I have a doubt on the following scenario:
I am trying to create a #Component class where in, I have an instance variable. Now, I want to create a new object of the instance variable for each request. I am not sure which one is the right way to do it?
**Option 1:**
#Component
public class ClassA {
private ClassB classB = new ClassB();
public ClassB create(){
return classB;
}
}
**Option 2:**
#Component
public class ClassA {
private ClassB classB = null;
public ClassB create(){
classB = new ClassB();
return classB;
}
}
**Option 3:**
#Component
public class ClassA {
public ClassB create(){
ClassB classB = new ClassB();
return classB;
}
}