This question already has answers here:
Is there a difference in setting fields inside or outside the constructor?
(8 answers)
Closed 8 years ago.
This is probably a 'duplicate', but I'm not sure how to search for this question...
I am initializing a non-static member variable at the declaration line:
public class A
{
private B b = new B();
...
}
I am doing it instead of initializing this variable inside the default constructor:
public class A
{
private B b;
public A()
{
b = new B();
}
...
}
Is there any difference between the two, except (perhaps) the former not being "ANSI Java" or something like that?
I am getting two different byte-codes (i.e., two different 'class' files) for the two implementations above, which leads me to believe that there might be run-time differences.
So I would like to know if I have any reason to expect anything different during run-time.
Thanks
The first one is a declaration and initialization at the same time .
In the second example instead you have the declaration of the b variable not initialized and then in the constructor you initialize the variable ...
The functional difference can come at the moment that you add another constructor, in that case the b variable should be initialized even in that constructor or if not, there will be a huge difference .
In the first case you have the variable initialized no matter how many constructor you implement ...
Honestly I don't understand how can you pretend to have the same bytecode, writing two different things as for this case .
No different in general (mean that declare outside and inside a constructor will behave something different). Just remind that initialize outside will run first, before come into some specific constructor. For example:
class A {
int a = 3;
public A() {
a = 4; // now a = 4. not 3
}
}
But, I often use them with different purpose :
Initialize variables inside constructor make it clearer and help you initialize something more complex. for example, put some logic code, put a loop to add items, ... that you cannot do when initialize outside of constructor scope.
When you have many overloading constructors, and some variables always declare same. Simple "state variable" such as isExist isEmpty ... I often initialize outside of constructor scope. So, all other constructors don't do the same thing.
There are no difference, both codes work well. I personally prefer the second way for a big class, meanwhile the first is preferd for small classes.
There is one small difference between this approaches!
When variable is declared inside constructor, there is chance that after some time second constructor will be created and this variable will be uninitialized. For fighting this declare this variable as final - if this is possible of course ;)
Other differences not exists :)
public class A
{
private B b;
public A() {
b = new B();
}
public A(int value) { // second constructor
}
...
}
After using A a = new A(5); field b is null.
The main difference is the order of function calls:
In the 1st case, method B() is called before method A().
In the 2nd case, method A() is called before method B().
An additional difference is what has been suggested in all other answers...
When a non-default constructor which does not initialize variable b exists:
In the 1st case, variable b will be initialized even when that constructor is used.
In the 2nd case, variable b will not be initialized whenever that constructor is used.
Related
Consider:
int a = 0;
int b = 3;
//Constructor 1
public ClassName (int a) {
this(a, b); //Error
//new ClassName(a, b) //No error
}
//Constructor 2
public ClassName (int a, int b) {
this.a = a;
this.b = b;
}
First question:
I get an error saying "b should be static". Why can't I use the default value (3) for b in this way?
Second question:
In the first constructor, if I use the comment outed part, I do not get an error. Is it an acceptable usage?
The use of instance variables in an explicit constructor invocation is prohibited by the JLS, Section 8.8.7.1.
An explicit constructor invocation statement in a constructor body may not refer to any instance variables or instance methods or inner classes declared in this class or any superclass, or use this or super in any expression; otherwise, a compile-time error occurs.
This prohibition on using the current instance explains why an explicit constructor invocation statement is deemed to occur in a static context (ยง8.1.3).
You referenced the instance variable b. The compiler didn't raise this error on a because it's a local variable, which shadows the instance variable a.
The "static context" may be why your IDE is suggesting to make b static, so it can be referenced. It makes sense; the ClassName part of the object isn't constructed yet. Replace that usage of b with something else, such as a static constant, or a literal int value.
To answer your other question, typing new ClassName(a, b) isn't an error because at this point, this instance has been constructed, and you're creating a separate, unrelated ClassName object.
First question: I get an error saying "b should be static". Why can't I use the default value (3) for b in this way?
The correct way to supply a default value for b to the other constructor is this(a, 3);. You cannot refer to instance variables until after this(...). That's just one of the rules of the language.
Second question: In the first constructor if I use the comment outed part I do not get an error. Is it an acceptable usage?
new ClassName(a, b); does something different. It creates a separate instance of the class. In my humble opinion it is probably not the best thing to do. People expect new to create one instance of a class, whereas using new ClassName in the constructor creates two.
When using variables in classes, it is important to note where that validity of scope is. You've instantiated new a,b variants of the variables there. You're tricking yourself into believing those are the same variables. Actually they're in another address space. If you want to use your class variables you'll have to take out the parameters to the functions. Then they'll sync with the class you're in, rather than isolating the arguments a, b to within the scope of your function,
This question already has answers here:
Should I instantiate instance variables on declaration or in the constructor?
(15 answers)
Closed 9 years ago.
We can do :
class A {
// some code
}
class B {
A obj = new A(); // ???
}
Query :
My understanding is that the instance obj (of class A) is not static therefore not available in Class memory of B
In that case, will it be initialized for every instance of B?
In the case that obj actually stays in Class memory of B (i.e., static), then when will the initialization of instance obj happen?
Either way, is this a good practice ?
Then why do we have constructors if we can do this?
Feel free to correct me.
Fields initialized like this are common practice.
You can think of them as being part of the constructor, similar to instance initializer blocks.
We still have constructors, because you want to take parameters and have complex logic sometimes.
The pattern is especially convenient if you have more than one constructor (the fields will be initialized for every code path).
A is not static therefore not available in Class memory.
Correct. You have to have an instance of B to get at the field A obj.
will it be preinitialized for every object of B ?
Yes. A separate new A will be created for every B created.
If this has to stay in obj memory then when will this initialization happen ?
N/A
Either way is it a good practice ?
Yes. It's called object composition and composing objects from other objects is one of the two main means of decomposing a problem using Object-Oriented design. The other one is inheritance.
Then why do we have constructors if we can do this ?
This is just syntactic sugar. All the below are equivalent.
class B {
A obj = new A(); // field initializer
}
class B {
A obj;
B() {
A = new A(); // initialized in constructor
}
}
class B {
A obj;
{ obj = new A(); } // instance initializer
}
As long as nothing reads obj during initialization, there's no observable difference between doing initialization in a field, constructor, or explicit initializer.
Sometimes it's just more convenient to assign a value where the field is declared.
A is not static therefore not available in Class memory.
Right.class A will be instantiated whenever B is instantiated
will it be preinitialized for every object of B ?
Yes.Whenever you are creating object of B, A object is also created
either way is it a good practice ?
Practically it is the same as instantiating through a constructor. So no problems of being a good or bad practice
Then why do we have constructors if we can do this ?
If you have multiple constructors, then you don't have to instantiate A in every constructor.
This question already has answers here:
why java polymorphism not work in my example
(3 answers)
Closed 6 years ago.
Generally Overriding is the concept of Re-defining the meaning of the member in the sub class.Why variables are not behaving like methods while Overriding in java ?
For instance:
class Base {
int a = 10;
void display() {
System.out.println("Inside Base :");
}
}
class Derived extends Base {
int a = 99;
#Override
// method overriding
void display() {
System.out.println("Inside Derived :");
}
}
public class NewClass {
public static void main(String... a) {
Derived d = new Derived();
Base b = d;
b.display(); // Dynamic method dispatch
System.out.println("a=" + b.a);
}
}
Since data member a is package access specified, it is also available to the Derived class. But generally while calling the overridden method using the base class reference, the method that is redefined in derived class is called (Dynamic method dispatch)..but it is not the same for the variable..why.?
EXPECTED OUTPUT
Inside Derived :
a=99
OBTAINED OUTPUT:
Inside Derived :
a=10
Prints 10 - why the variable does not behave similar to method in the derived class?
Why the variables are not allowed to be overridden in the sub class?
You typed b as an instance of Base. So when the compiler needs to resolve b.a, it looks to the definition of Base for the meaning of b.a. There is no polymorphism for instance fields.
Because the only thing that polymorphism ever applies to in Java is instance method.
Hence, you can neither override static members, nor the instance member fields. By, having these members in a derived class with the same names you're simply hiding them with a new definition.
System.out.println("a="+b.a);
Although, Base b may point to a sub-class object (at runtime) the a above has already been bound to Base class at compile time (static binding). Hence, it prints 10.
Variables behave like that because they lack behavior. In other words, variables are passive.
There is nothing about a variable's definition that a derived class can reasonably change by overriding:
It cannot change its type, because doing so may break methods of the base class;
It cannot reduce its visibility, because that would break the substitution principle.
It cannot make it final without making it useless to the base class.
Therefore, member variables declared in derived classes hide variables from the base class.
There is no way to override a class variable. You do not override class variables in Java you hide them. Overriding is for instance methods.
In this case, it might be a good idea to write a getter method:
public int getA(){
return 99;
}
Now you can override it in a derived class.
First, we don't override any class variable. Methods only.
Second, if you would like to see that the variable value has been updated or replaced, you should rather declare it as "static int" instead of "int". In this way, it will work as everybody is sharing the same variable, and the new value will be put on it.
Third, if you would like to see that the variable value being assigned and used differently, you could design it as passing a parameter in constructor, or something similar, to make it work accordingly as you desire.
The answer to this has to do with variable scoping, not polymorphism. In other words, you're overriding that variable in the class scope. So, d.a will return the variable in Derived's class scope, but b.a will return the variable in Base's class scope.
In OOP (Object Oriented Programming) the idea is to hide the data in the object and let object only communicate with invoking methods. That's why variables cannot be overloaded, in fact they are "scoped"/"attached" to a specific class.
Also the derived class should not define a again, it is already defined in the base class, so simply set a on the object to the desired value, e.g:
class Base {
private int a = 10;
public int getA() { return a; }
public void setA(inta) { this.a = a; }
}
class Derived extends Base {
// adding new variables, override methods, ...
}
// then later:
Derived d = new Derived();
d.setA(99); // override the default value 10
What would happen if variables could override other variables? Suddenly your class has to be aware of what variables the parent class is using, lest you accidentally override one and break whatever was using it in the parent class. The whole point of encapsulation is to avoid having that kind of intimate knowledge of another object's internal state. So instead, variables shadow same-named other variables, and which one you see depends on what type you're trying to reach the variable through.
There's hope, though. If all you want is to override the value, you don't have to redeclare the variable. Just change the value in an init block. If the base class is harmed by you doing that, then it chose the wrong visibility for that variable.
class Base {
int a = 10;
}
class Derived extends Base {
{ a = 99; }
}
Of course, this doesn't work very well for final variables.
we don't override any class variable. Methods only.
If you would like to see that the variable value has been updated or
replaced, you should rather declare it as "static int" instead of
"int". In this way, it will work as everybody is sharing the same
variable, and the new value will be put on it.
If you would like to see that the variable value being assigned and
used differently, you could design it as passing a parameter in
constructor, or something similar, to make it work accordingly as
you desire.
Moreover, if variables are overridden then what is left with a parent class of its own,it breaches the class security if java would give the access to change the value of variable of parent class.
I have recently found out that no argument constructor and multiple argument constructor cannnot call each other in turns. What is the underlying reason of this limitation? Some might say that constructors are where resources are initialised. So they must not be called recursively. I want to know if this is the only reason or not. Functions/methods/procedures can be called recursively. Why not constructors?
The answer lies in the fact that the call to another constructor is the first line of any constructor and hence your if condition to break out of recursion will never be executed and hence stack overflow.
The main purpose of the constructor is to initialize all the global variables described in a particular class.
For Example:
public class Addition(){
int value1;
int value2;
public Addition(){ // default constructor
a=10;
b=10;
}
public Addition(int a, int b){
this(); // constructors having parameters , overloaded constructor
value1=a;
value2=b;
}
}
public class Main(){
public static void main(){
Addition addition = new Addition(); //or
Addition addition = new Addition(15,15);
}
}
Here, if you want to make instance of the class you can either make instance by calling default constructor or by calling constructor having parameters. So the constructors are overloaded and not overridden. If you want to call another constructor, that can only be done be putting either this() or super() in the first line of the constructor. But this is not prefferable.
Constructors are not intended to be called explicitly outside object initialization, because it's restricted in most (I guess all) languages. Instead, you can create an additional protected Init(...) member function and call it inside the constructor.
Your statement that constructor cannot call other constructors are not true for every programming languages. At least I know Java can do this, while C++ cannot. But you could easily overcome this limitation by writing a private __init function and let all your constructors call it.
In all languages you've listed objects contain finite (and normally short) set of properties. Each property could contain recursive structure (i.e. list), but it still represented by a single property in the object.
I don't see need to recursively call constructors. It feels like a strange use recursion to initialize several well know properties.
As you've said you can call constructors in non-recursive way to share code in some languages you've mentioned.
C#: Using Constructors
public Employee(int weeklySalary, int numberOfWeeks)
: this(weeklySalary * numberOfWeeks)
{
}
class A
{
int i=10;
void show()
{
System.out.println("class A");
}
}
class B extends A
{
int i=5;
public void show()
{
System.out.println("class B");
}
}
class M
{
public static void main(String s[])
{
A a=new B();
a.show();
System.out.println(a.i);
}
}
OUTPUT= class B
10
If class A method is overridden by class B method then why not the variable 'i'?
Because variables are not virtual, only methods are.
It is not overwritten, but hidden. In your output you specifically requested the value of a.i, not ((B)a).i.
This is a "feature" of the implementation. In memory, this looks like so:
a:
pointer to class A
int i
b:
pointer to class B
int i (from A)
int i (from B)
When you access i in an instance of B, Java needs to know which variable you mean. It must allocate both since methods from class A will want to access their own field i while methods from B will want their own i (since you chose to create a new field i in B instead of making A.i visible in B). This means there are two i and the standard visibility rules apply: Whichever is closer will win.
Now you say A a=new B(); and that's a bit tricky because it tells Java "treat the result from the right hand side as if it were an instance of A".
When you call a method, Java follows the pointer to the class (first thing in the object in memory). There, it finds a list of methods. Methods overwrite each other, so when it looks for the method show(), it will find the one defined in B. This makes method access fast: You can simply merge all visible methods in the (internal) method list of class B and each call will mean a single access to that list. You don't need to search all classes upwards for a match.
Field access is similar. Java doesn't like searching. So when you say B b = new B();, b.i is obviously from B. But you said A a = new B() telling Java that you prefer to treat the new instance as something of type A. Java, lazy as it is, looks into A, finds a field i, checks that you can see that field and doesn't even bother to look at the real type of a anymore (because that would a) be slow and b) would effectively prevent you from accessing both i fields by casting).
So in the end, this is because Java optimizes the field and method lookup.
Why no field overrides in Java though?
Well, because instance field lookups in Java happen at compile time: Java simply gives you the value of the field at a given offset in object's memory (based on the type information at hand during compilation: in this case a is declared to be of type A).
void foo() {
A a = new B();
int val = a.i; // compiler uses type A to compute the field offset
}
One may ask "Why didn't compiler use type B since it knows that a is in fact an instance of B? Isn't it obvious from the assignment just above?". Of course, in the case above, it's relatively obvious and compiler may try to be smarter and figure it out.
But that's compiler design "rat hole", what if a "trickier" piece of code is encountered, like so:
void foo(A a) {
int val = a.i;
}
If compiler were "smarter", it would become its job to look at all invocations of foo() and see what real type was used, which is an impossible job since compiler can not predict what other crazy things may be passed to foo() by unknown or yet unwritten callers.
It's a design decision by the developers of Java, and is documented in the Java Language Specification.
A method with the same method signature as a method in its parent class overrides the method in its parent class.
A variable with the same name as a variable in its parent class hides the parent's variable.
The difference is that hidden values can be accessed by casting the variable to its parent type, while overridden methods will always execute the child class's method.
As others have noted, in C++ and C#, to get the same override behavior as Java, the methods need to be declared virtual.
a is an instance of A. You call the constructor B(). But it is still a A class.
That is why i equals 10;
The override from the method will be succeded.
Note a class starts not with
public class A()
but with;
public class A { ... }
Tip: You can use setters and getters to make sure of what data-members you use.
Or: You simply can set the values at the constructor instead of the class declaration.
Because by default the variables are private. You must declare it as "protected", then will be properly inherited.