Reputation: 18139
public class Test {
int value = 100;
public Test() {
}
}
And
public class Test {
int value;
public Test() {
value = 100;
}
}
Are equivalent, right? Is there a reason why I'd prefer to do one over the other? Obviously if the constructor takes parameters that are later given to the fields is a reason:
public class Test {
int value;
public Test(int value) {
this.value = value;
}
}
Or perhaps I need to do some special calculation.
But if I don't do that, is there another good reason?
Upvotes: 7
Views: 1509
Reputation: 923
public class Test {
int value = 100;
public Test() {
}
}
This works well when the initialization value is available and you may declare and initialize field on one line. However, this form of initialization has limitations because of its simplicity. If initialization requires some logic (for example, error handling or a validation or condition), simple assignment is inadequate. When you are using constructor initialization, you may do error handling or other logic. To provide the same capability for class variables, the Java programming language includes static initialization blocks. There are also another two ways to initialize instance variables:
initializer blocks
{ // initialization }
final methods
class Foo{
int age=initAge();
protected int initAge(){
//initialization code
}
}
Upvotes: 1
Reputation: 7282
I'm not talking about bytecode, but they can differ semantically (if you have multiple constructors),
The field will be always initialized to 100 if you define it as below, no matter which constructor is called:
int field = 100;
but otherwise you shall initialize the field in each constructor.
Your class may have just a single constructor, but just think, will there be any other constructor in future releases of your class?
Upvotes: 0
Reputation: 3186
Currently in your example, there is just one field and you are deciding which way of initializing is better than the other.
But, if you increase the complexity by initializing a lot of fields (say 30 or 40), then it does make a lot of difference.
In this situation, consider what Joshua Bloch has to say on initializing through constructors.
Below is the summary,
Upvotes: 0
Reputation: 2260
Well it all really depends on how you plan on using this. I'm going to assume that you don't plan to make value
static but it's just there for internal purposes.
Firstly lets look at the bytecode.
D:\eclipse\workspace\asdf\bin>javap -c A.class
Compiled from "A.java"
public class A {
int value;
public A();
Code:
0: aload_0
1: invokespecial #10 // Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 100
7: putfield #12 // Field value:I
10: return
}
D:\eclipse\workspace\asdf\bin>javap -c B.class
Compiled from "B.java"
public class B {
int value;
public B();
Code:
0: aload_0
1: invokespecial #10 // Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 100
7: putfield #12 // Field value:I
10: return
}
D:\eclipse\workspace\asdf\bin>
Guess what? Exactly the same! Why? Because you can't USE value until you make an object by using the new
keyword.
The oracle docs states that:
As you have seen, you can often provide an initial value for a field in its declaration:
public class BedAndBreakfast {
// initialize to 10
public static int capacity = 10;
// initialize to false
private boolean full = false;
}
This works well when the initialization value is available and the initialization can be put on one line. However, this form of initialization has limitations because of its simplicity. If initialization requires some logic (for example, error handling or a for loop to fill a complex array), simple assignment is inadequate. Instance variables can be initialized in constructors, where error handling or other logic can be used. To provide the same capability for class variables, the Java programming language includes static initialization blocks.
So now you have confirmation that the whole point of doing it in the constructor is if you are doing something complex like initializing an array otherwise feel free to do it right there when you declare the field.
If you WERE to use static
then you are obviously doing two different things. It's almost like a check to see if someone has ever created an instance of this object or not. Your variable would be 0
until someone creates an object and then it would be 100
afterward.
Upvotes: 4
Reputation: 106389
Well, it depends.
With the second case, value
would be populated with its default value of 0
, only to be reassigned at instantiation with 100
. In the first case, value
is just instantly given the value of 100
.
Semantically, this would help a programmer - they would see that this particular value means something a little more than just it being arbitrary (although, it should be a constant value somewhere).
Programmatically, there's no pain if a primitive is set to some initial value. It means that there's something in there for you to use, and if your program depends on there being a non-negative or false value, by George it will work.
Things get more explicit when dealing with object references. Take, for instance, these two classes:
public class Foo {
List<String> elements;
public Foo() {
}
public Foo(String... items) {
elements = new ArrayList<>();
for(String item : items) {
elements.add(item);
}
}
}
public class Bar {
List<String> elements = new ArrayList<>();
public Bar() {
}
public Bar(String... items) {
for(String item : items) {
elements.add(item);
}
}
}
There are intentionally no-arg constructors to hammer home the point - for Foo
, if I attempt to use elements
, then I'm in a bit of trouble if I don't use the appropriate constructor - elements
is null
!* I could then just instantiate it whenever I needed it, but I would very much want to avoid destroying a potentially newed and populated list.
That means a lot of code looking something like this:
if(elements == null) {
elements = new ArrayList<>();
}
...then I have to worry about it being thread safe. Sheesh, talk about a hassle.
With Bar
, I'm guaranteed that at instantiation, there is an instance of a list in elements
, so I don't have to worry about it being null
.**
This is known as eager instantiation. You really don't want to live without that object, so why wait until you think you need it (or lazily instantiate)?
*: The default value for all reference types is null
.
**: You do have to worry about that being overwritten, but that's a concern outside of the scope of this question.
Upvotes: 1
Reputation: 227
Whenever a class is created the constructor is initialized first. So, when you declare or define a variable inside the constructor the memory is allocated to that variable at first and then the process will be continued.
Upvotes: 0
Reputation: 11648
If you're not doing any calculation or not taking any parameters, there's no difference in any of those above two, whether you initialize or not initialize those variable inside constructor.
If you declare them as the first one like you declare as:
public class Test {
int value = 100;
public Test() {
}
}
It would be more of a readable format as you're assigning them value directly, no need to view from constructor.
It would be better also for If you have more than one constructor, you don't have to repeat the initializations (and you cannot forget them).
Upvotes: 0
Reputation: 201409
Field initialization code is copied into each constructor... if you had multiple constructors and wanted the field initialized with the same value in each (or even just most) then it would be better to initialize at declaration and override the value in the constructor.
Upvotes: 1