Related
Is there any advantage for either approach?
Example 1:
class A {
B b = new B();
}
Example 2:
class A {
B b;
A() {
b = new B();
}
}
There is no difference - the instance variable initialization is actually put in the constructor(s) by the compiler.
The first variant is more readable.
You can't have exception handling with the first variant.
There is additionally the initialization block, which is as well put in the constructor(s) by the compiler:
{
a = new A();
}
Check Sun's explanation and advice
From this tutorial:
Field declarations, however, are not part of any method, so they cannot be executed as statements are. Instead, the Java compiler generates instance-field initialization code automatically and puts it in the constructor or constructors for the class. The initialization code is inserted into a constructor in the order it appears in the source code, which means that a field initializer can use the initial values of fields declared before it.
Additionally, you might want to lazily initialize your field. In cases when initializing a field is an expensive operation, you may initialize it as soon as it is needed:
ExpensiveObject o;
public ExpensiveObject getExpensiveObject() {
if (o == null) {
o = new ExpensiveObject();
}
return o;
}
And ultimately (as pointed out by Bill), for the sake of dependency management, it is better to avoid using the new operator anywhere within your class. Instead, using Dependency Injection is preferable - i.e. letting someone else (another class/framework) instantiate and inject the dependencies in your class.
Another option would be to use Dependency Injection.
class A{
B b;
A(B b) {
this.b = b;
}
}
This removes the responsibility of creating the B object from the constructor of A. This will make your code more testable and easier to maintain in the long run. The idea is to reduce the coupling between the two classes A and B. A benefit that this gives you is that you can now pass any object that extends B (or implements B if it is an interface) to A's constructor and it will work. One disadvantage is that you give up encapsulation of the B object, so it is exposed to the caller of the A constructor. You'll have to consider if the benefits are worth this trade-off, but in many cases they are.
I got burned in an interesting way today:
class MyClass extends FooClass {
String a = null;
public MyClass() {
super(); // Superclass calls init();
}
#Override
protected void init() {
super.init();
if (something)
a = getStringYadaYada();
}
}
See the mistake? It turns out that the a = null initializer gets called after the superclass constructor is called. Since the superclass constructor calls init(), the initialization of a is followed by the a = null initialization.
my personal "rule" (hardly ever broken) is to:
declare all variables at the start of
a block
make all variables final unless they
cannot be
declare one variable per line
never initialize a variable where
declared
only initialize something in a
constructor when it needs data from
the constructor to do the
initialization
So I would have code like:
public class X
{
public static final int USED_AS_A_CASE_LABEL = 1; // only exception - the compiler makes me
private static final int A;
private final int b;
private int c;
static
{
A = 42;
}
{
b = 7;
}
public X(final int val)
{
c = val;
}
public void foo(final boolean f)
{
final int d;
final int e;
d = 7;
// I will eat my own eyes before using ?: - personal taste.
if(f)
{
e = 1;
}
else
{
e = 2;
}
}
}
This way I am always 100% certain where to look for variables declarations (at the start of a block), and their assignments (as soon as it makes sense after the declaration). This winds up potentially being more efficient as well since you never initialize a variable with a value that is not used (for example declare and init vars and then throw an exception before half of those vars needed to have a value). You also do not wind up doing pointless initialization (like int i = 0; and then later on, before "i" is used, do i = 5;.
I value consistency very much, so following this "rule" is something I do all the time, and it makes it much easier to work with the code since you don't have to hunt around to find things.
Your mileage may vary.
Example 2 is less flexible. If you add another constructor, you need to remember to instantiate the field in that constructor as well. Just instantiate the field directly, or introduce lazy loading somewhere in a getter.
If instantiation requires more than just a simple new, use an initializer block. This will be run regardless of the constructor used. E.g.
public class A {
private Properties properties;
{
try {
properties = new Properties();
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("file.properties"));
} catch (IOException e) {
throw new ConfigurationException("Failed to load properties file.", e); // It's a subclass of RuntimeException.
}
}
// ...
}
Using either dependency injection or lazy initialization is always preferable, as already explained thoroughly in other answers.
When you don't want or can't use those patterns, and for primitive data types, there are three compelling reasons that I can think of why it's preferable to initialize the class attributes outside the constructor:
avoided repetition = if you have more than one constructor, or when you will need to add more, you won't have to repeat the initialization over and over in all the constructors bodies;
improved readability = you can easily tell with a glance which variables will have to be initialized from outside the class;
reduced lines of code = for every initialization done at the declaration there will be a line less in the constructor.
I take it is almost just a matter of taste, as long as initialization is simple and doesn't need any logic.
The constructor approach is a bit more fragile if you don't use an initializer block, because if you later on add a second constructor and forget to initialize b there, you'll get a null b only when using that last constructor.
See http://java.sun.com/docs/books/tutorial/java/javaOO/initial.html for more details about initialization in Java (and for explanations on initalizer blocks and other not well known initialization features).
I've not seen the following in the replies:
A possible advantage of having the initialisation at the time of declaration might be with nowadays IDE's where you can very easily jump to the declaration of a variable (mostly
Ctrl-<hover_over_the_variable>-<left_mouse_click>) from anywhere in your code. You then immediately see the value of that variable. Otherwise, you have to "search" for the place where the initialisation is done (mostly: constructor).
This advantage is of course secondary to all other logical reasonings, but for some people that "feature" might be more important.
Both of the methods are acceptable. Note that in the latter case b=new B() may not get initialized if there is another constructor present. Think of initializer code outside constructor as a common constructor and the code is executed.
I think Example 2 is preferable. I think the best practice is to declare outside the constructor and initialize in the constructor.
The second is an example of lazy initialization. First one is more simple initialization, they are essentially same.
There is one more subtle reason to initialize outside the constructor that no one has mentioned before (very specific I must say). If you are using UML tools to generate class diagrams from the code (reverse engineering), most of the tools I believe will note the initialization of Example 1 and will transfer it to a diagram (if you prefer it to show the initial values, like I do). They will not take these initial values from Example 2. Again, this is a very specific reason - if you are working with UML tools, but once I learned that, I am trying to take all my default values outside of constructor unless, as was mentioned before, there is an issue of possible exception throwing or complicated logic.
The second option is preferable as allows to use different logic in ctors for class instantiation and use ctors chaining. E.g.
class A {
int b;
// secondary ctor
A(String b) {
this(Integer.valueOf(b));
}
// primary ctor
A(int b) {
this.b = b;
}
}
So the second options is more flexible.
It's quite different actually:
The declaration happens before construction. So say if one has initialized the variable (b in this case) at both the places, the constructor's initialization will replace the one done at the class level.
So declare variables at the class level, initialize them in the constructor.
class MyClass extends FooClass {
String a = null;
public MyClass() {
super(); // Superclass calls init();
}
#Override
protected void init() {
super.init();
if (something)
a = getStringYadaYada();
}
}
Regarding the above,
String a = null;
null init could be avoided since anyway it's the default.
However, if you were to need another default value,
then, because of the uncontrolled initialization order,
I would fix as follow:
class MyClass extends FooClass
{
String a;
{
if( a==null ) a="my custom default value";
}
...
I have a question regarding the java garbage collection and enum types.
Lets say I have an enum like so:
enum ConnectionHelper {
INSTANCE;
private boolean initialized = false;
private static int someVar;
ConnectionHelper initialize() {
if (!initialized) {
// Do some initialisation...
someVar = 10;
// NOTE: 1
initialized = true;
}
return this;
}
void start() {
// NOTE: 2
if (!initialized) {
throw new IllegalStateException("ConnectionHelper has to be initialized.");
}
// do some work...
}
Now is there a scenario where initialized may revert back to FALSE due to the garbage collector? The reason I'm asking because if thats the case I need to take additional precautions for this scenario.
And also, if I represent en singleton with an enum, would it matter if I use static or non-static variables for state? For example, in this example, there are two variables; someVar and initialised, would it make a difference to question 1 if initialized was static as well? Or if both were non-static?
Thanks!
We can answer all kind of “will the garbage collector make this program behave strangely” questions with “no”, in general. The very purpose of a garbage collector is to clean up the memory of unused objects transparently, without your program even noticing. Producing an observable behavior like a variable flipping from trueto false is definitely outside the actions allowed for a garbage collector.
That said, your program is not thread safe. If multiple threads access your ConnectionHelper without additional synchronization, they may perceive inconsistent results, including seeing false for the initialized variable while another thread already saw true for it at an earlier time from an external clock’s perspective, or seeing true for initialized while still not seeing the value of 10 written for someVar.
The solution is simple. Don’t implement a superfluous lazy initialization. The enum constants are initialized during the class initialization, which is already lazy (as specified in JLS §12.4.1) and made thread safe (as specified in JLS §12.4.2) by the JVM.
enum ConnectionHelper {
INSTANCE;
private static final int someVar = 10;
void start() {
// do some work, use the already initialized someVar...
}
}
or
enum ConnectionHelper {
INSTANCE;
private final int someVar = 10;
void start() {
// do some work, use the already initialized someVar...
}
}
or
enum ConnectionHelper {
INSTANCE;
private final int someVar;
ConnectionHelper() {
someVar = 10; // as place-holder for more complex initialization
}
void start() {
// do some work, use the already initialized someVar...
}
}
it doesn’t matter whether you declare the variable static or not.
The first thread calling start() will perform the class initialization, including the initialization of someVar. If other threads call the method while the initialization is still ongoing, they will wait for its completion. After the completion of the initialization, all threads may execute the start() method using the initialized values without any slowdown.
Garbage collection is not expected on enum types. Your ConnectionHelper.INSTANCE can not be dereferenced, so the object will always be kept in memory once instantiated.
So, to your questions:
AD 1: No, it can not revert. The only way to set it back to false is to set it manually.
AD 2: No difference for a singleton. There would be a difference if you had more instances, as they would share static variables and not the usual ones.
What sort of optimizations would Java Runtime perform on the follow snippet of code? The bytecode doesn't reveal any optimization however I feel that Java should take the last value of the for loop without running the entire for loop since String is a rudimentary Java class.
NOTE. this question was asked on a class test; however, I couldn't provide enough evidence to back my claim.
public class Main {
public static void main(String[] args) {
String str = null;
for (long i = 0; i < 10000000000L; i++) {
str = new String("T");
}
System.out.println(str);
}
}
While I can't speak to exactly what the jit compiler is doing, the optimization you are asking it to do (to determine that it is safe to skip the loop body entirely) is actually extremely difficult to do, and so I highly doubt it it is done. This is true regardless of String being a "rudimentary Java class".
To understand better, first let's assume that instead of String, we are creating instances of an arbitrary class Foo. It would only be safe to skip the creation of all those Foo objects if we knew two things: that calling new Foo() didn't have any observable side effects; and that no references to Foo "escaped" the loop body.
An observable side effect would be something like setting the value of a static member (e.g. if the Foo class kept a static count of all the times Foo() had been called). An example of a reference escaping would be if the this variable inside of Foo() was passed somewhere else.
Note that it isn't enough to just look at Foo(), you need to look at Foo's superclass' constructor (and all the way up the chain to Object). And then you need to look at all the code that gets executed upon initialization of each of those objects. And then look at all the code that gets called by that code. That would be a tremendous amount of analysis to do "just-in-time".
public class Foo extends Bazz{
static int count = 0;
public Foo(){
// Implicit call to Bazz() has side effect
count++; // side effect
Bazz.onNewFoo(this); // reference escaping
}
Bazz bazz = new Bazz(); // side effect
{
Bazz.onNewBazz(this.bazz); // reference escaping
}
}
class Bazz{
static int count = 0;
static List<Foo> fooList = new LinkedList<>();
static List<Bazz> bazzList = new LinkedList<>();
static void onNewFoo(Foo foo){
fooList.add(foo);
}
static void onNewBazz(Bazz bazz){
bazzList.add(bazz);
}
public Bazz(){
count++;
}
}
You might think we should just let javac do this analysis and optimization for us. The problem with that is, that there is no way to guarantee that the version of Foo() that was on the classpath at compile-time will be the same as that which is on the classpath at run-time. (Which is a very valuable feature of Java - it allows me to move my application from Glassfish to Tomcat without recompiling). So we can't trust analysis done at compile-time.
Finally, realize that String is no different from Foo. We'd still need to run that analysis, and there is no way to do that analysis in advance (which I why I can upgrade my JRE without recompiling my apps)
Searched a lot about phantom reference but unable to find its practical usage. And logically the get() method returns null in case of Phantom References
You can follow this blog:
What good are PhantomReferences? I'm only aware of two serious cases
for them: first, they allow you to determine exactly when an object
was removed from memory. They are in fact the only way to determine
that. This isn't generally that useful, but might come in handy in
certain very specific circumstances like manipulating large images: if
you know for sure that an image should be garbage collected, you can
wait until it actually is before attempting to load the next image,
and therefore make the dreaded OutOfMemoryError less likely.
Second, PhantomReferences avoid a fundamental problem with
finalization: finalize() methods can "resurrect" objects by creating
new strong references to them. So what, you say? Well, the problem is
that an object which overrides finalize() must now be determined to be
garbage in at least two separate garbage collection cycles in order to
be collected. When the first cycle determines that it is garbage, it
becomes eligible for finalization. Because of the (slim, but
unfortunately real) possibility that the object was "resurrected"
during finalization, the garbage collector has to run again before the
object can actually be removed. And because finalization might not
have happened in a timely fashion, an arbitrary number of garbage
collection cycles might have happened while the object was waiting for
finalization. This can mean serious delays in actually cleaning up
garbage objects, and is why you can get OutOfMemoryErrors even when
most of the heap is garbage.
Also read: The Mysterious Phantom Reference
Consider the following code.
public class Foo {
private String bar;
public Foo(String bar) {
this.bar = bar;
}
public String foo() {
return bar;
}
}
So lets say after the object has been completely dereferenced by the
application I want to some how call foo(). Here is some code that I
expected to work that would do this with one niggle.
// initialize
ReferenceQueue<Foo> queue = new ReferenceQueue<Foo>();
ArrayList< PhantomReference<Foo>> list=new ArrayList<PhantomReference<Foo>>();
for ( int i = 0; i < 10; i++) {
Foo o = new Foo( Integer.toOctalString( i));
list.add(new PhantomReference<Foo>(o, queue));
}
// make sure the garbage collector does it’s magic
System.gc();
// lets see what we’ve got
Reference<? extends Foo> referenceFromQueue;
for ( PhantomReference<Foo> reference : list)
System.out.println(reference.isEnqueued());
while ( (referenceFromQueue = queue.poll()) != null) {
System.out.println(referenceFromQueue.get());
referenceFromQueue.clear();
}
PhantomReference takes an instance of Foo and a ReferenceQueue. Since
no handles are kept to Foo, it should immediately be dead. Next, tell
the VM to collect as there isn’t enough in heap for it to trigger a
collection naturally. The first thing I’m going to ask the
PhantomReference is; have you been enqueued. In this case the answer
will be true. Next I ask the queue for the reference but as you can
see, calling get() always returns null. About the only solution that
made sense is to wrap the resources or objects you wanted to interact
with in a subclass of PhantomReference.
public class FinalizeStuff<Foo> extends PhantomReference<Foo> {
public FinalizeStuff(Foo foo, ReferenceQueue<? super Foo> queue) {
super(foo, queue);
}
public void bar() {
System.out.println("foobar is finalizing resources");
}
}
In this case I’m not going to wrap Foo in the subclass as that would
seem to violate the spirit of PhantomReference. Instead I’m going to
wrap resources associated with Foo and interact with them. Now I can
do this.
// initialize
ReferenceQueue<Foo> queue = new ReferenceQueue<Foo>();
ArrayList< FinalizeStuff<Foo>> list = new ArrayList<FinalizeStuff<Foo>>();
ArrayList<Foo> foobar = new ArrayList<Foo>();
for ( int i = 0; i < 10; i++) {
Foo o = new Foo( Integer.toOctalString( i));
foobar.add(o);
list.add(new FinalizeStuff<Foo>(o, queue));
}
// release all references to Foo and make sure the garbage collector does it’s magic
foobar = null;
System.gc();
// should be enqueued
Reference<? extends Foo> referenceFromQueue;
for ( PhantomReference<Foo> reference : list) {
System.out.println(reference.isEnqueued());
}
// now we can call bar to do what ever it is we need done
while ( (referenceFromQueue = queue.poll()) != null) {
((FinalizeStuff)referenceFromQueue).bar();
referenceFromQueue.clear();
}
Is there any advantage for either approach?
Example 1:
class A {
B b = new B();
}
Example 2:
class A {
B b;
A() {
b = new B();
}
}
There is no difference - the instance variable initialization is actually put in the constructor(s) by the compiler.
The first variant is more readable.
You can't have exception handling with the first variant.
There is additionally the initialization block, which is as well put in the constructor(s) by the compiler:
{
a = new A();
}
Check Sun's explanation and advice
From this tutorial:
Field declarations, however, are not part of any method, so they cannot be executed as statements are. Instead, the Java compiler generates instance-field initialization code automatically and puts it in the constructor or constructors for the class. The initialization code is inserted into a constructor in the order it appears in the source code, which means that a field initializer can use the initial values of fields declared before it.
Additionally, you might want to lazily initialize your field. In cases when initializing a field is an expensive operation, you may initialize it as soon as it is needed:
ExpensiveObject o;
public ExpensiveObject getExpensiveObject() {
if (o == null) {
o = new ExpensiveObject();
}
return o;
}
And ultimately (as pointed out by Bill), for the sake of dependency management, it is better to avoid using the new operator anywhere within your class. Instead, using Dependency Injection is preferable - i.e. letting someone else (another class/framework) instantiate and inject the dependencies in your class.
Another option would be to use Dependency Injection.
class A{
B b;
A(B b) {
this.b = b;
}
}
This removes the responsibility of creating the B object from the constructor of A. This will make your code more testable and easier to maintain in the long run. The idea is to reduce the coupling between the two classes A and B. A benefit that this gives you is that you can now pass any object that extends B (or implements B if it is an interface) to A's constructor and it will work. One disadvantage is that you give up encapsulation of the B object, so it is exposed to the caller of the A constructor. You'll have to consider if the benefits are worth this trade-off, but in many cases they are.
I got burned in an interesting way today:
class MyClass extends FooClass {
String a = null;
public MyClass() {
super(); // Superclass calls init();
}
#Override
protected void init() {
super.init();
if (something)
a = getStringYadaYada();
}
}
See the mistake? It turns out that the a = null initializer gets called after the superclass constructor is called. Since the superclass constructor calls init(), the initialization of a is followed by the a = null initialization.
my personal "rule" (hardly ever broken) is to:
declare all variables at the start of
a block
make all variables final unless they
cannot be
declare one variable per line
never initialize a variable where
declared
only initialize something in a
constructor when it needs data from
the constructor to do the
initialization
So I would have code like:
public class X
{
public static final int USED_AS_A_CASE_LABEL = 1; // only exception - the compiler makes me
private static final int A;
private final int b;
private int c;
static
{
A = 42;
}
{
b = 7;
}
public X(final int val)
{
c = val;
}
public void foo(final boolean f)
{
final int d;
final int e;
d = 7;
// I will eat my own eyes before using ?: - personal taste.
if(f)
{
e = 1;
}
else
{
e = 2;
}
}
}
This way I am always 100% certain where to look for variables declarations (at the start of a block), and their assignments (as soon as it makes sense after the declaration). This winds up potentially being more efficient as well since you never initialize a variable with a value that is not used (for example declare and init vars and then throw an exception before half of those vars needed to have a value). You also do not wind up doing pointless initialization (like int i = 0; and then later on, before "i" is used, do i = 5;.
I value consistency very much, so following this "rule" is something I do all the time, and it makes it much easier to work with the code since you don't have to hunt around to find things.
Your mileage may vary.
Example 2 is less flexible. If you add another constructor, you need to remember to instantiate the field in that constructor as well. Just instantiate the field directly, or introduce lazy loading somewhere in a getter.
If instantiation requires more than just a simple new, use an initializer block. This will be run regardless of the constructor used. E.g.
public class A {
private Properties properties;
{
try {
properties = new Properties();
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("file.properties"));
} catch (IOException e) {
throw new ConfigurationException("Failed to load properties file.", e); // It's a subclass of RuntimeException.
}
}
// ...
}
Using either dependency injection or lazy initialization is always preferable, as already explained thoroughly in other answers.
When you don't want or can't use those patterns, and for primitive data types, there are three compelling reasons that I can think of why it's preferable to initialize the class attributes outside the constructor:
avoided repetition = if you have more than one constructor, or when you will need to add more, you won't have to repeat the initialization over and over in all the constructors bodies;
improved readability = you can easily tell with a glance which variables will have to be initialized from outside the class;
reduced lines of code = for every initialization done at the declaration there will be a line less in the constructor.
I take it is almost just a matter of taste, as long as initialization is simple and doesn't need any logic.
The constructor approach is a bit more fragile if you don't use an initializer block, because if you later on add a second constructor and forget to initialize b there, you'll get a null b only when using that last constructor.
See http://java.sun.com/docs/books/tutorial/java/javaOO/initial.html for more details about initialization in Java (and for explanations on initalizer blocks and other not well known initialization features).
I've not seen the following in the replies:
A possible advantage of having the initialisation at the time of declaration might be with nowadays IDE's where you can very easily jump to the declaration of a variable (mostly
Ctrl-<hover_over_the_variable>-<left_mouse_click>) from anywhere in your code. You then immediately see the value of that variable. Otherwise, you have to "search" for the place where the initialisation is done (mostly: constructor).
This advantage is of course secondary to all other logical reasonings, but for some people that "feature" might be more important.
Both of the methods are acceptable. Note that in the latter case b=new B() may not get initialized if there is another constructor present. Think of initializer code outside constructor as a common constructor and the code is executed.
I think Example 2 is preferable. I think the best practice is to declare outside the constructor and initialize in the constructor.
The second is an example of lazy initialization. First one is more simple initialization, they are essentially same.
There is one more subtle reason to initialize outside the constructor that no one has mentioned before (very specific I must say). If you are using UML tools to generate class diagrams from the code (reverse engineering), most of the tools I believe will note the initialization of Example 1 and will transfer it to a diagram (if you prefer it to show the initial values, like I do). They will not take these initial values from Example 2. Again, this is a very specific reason - if you are working with UML tools, but once I learned that, I am trying to take all my default values outside of constructor unless, as was mentioned before, there is an issue of possible exception throwing or complicated logic.
The second option is preferable as allows to use different logic in ctors for class instantiation and use ctors chaining. E.g.
class A {
int b;
// secondary ctor
A(String b) {
this(Integer.valueOf(b));
}
// primary ctor
A(int b) {
this.b = b;
}
}
So the second options is more flexible.
It's quite different actually:
The declaration happens before construction. So say if one has initialized the variable (b in this case) at both the places, the constructor's initialization will replace the one done at the class level.
So declare variables at the class level, initialize them in the constructor.
class MyClass extends FooClass {
String a = null;
public MyClass() {
super(); // Superclass calls init();
}
#Override
protected void init() {
super.init();
if (something)
a = getStringYadaYada();
}
}
Regarding the above,
String a = null;
null init could be avoided since anyway it's the default.
However, if you were to need another default value,
then, because of the uncontrolled initialization order,
I would fix as follow:
class MyClass extends FooClass
{
String a;
{
if( a==null ) a="my custom default value";
}
...