what is the difference in following two pieces of code:
class B{
B(){}
}
//1)
class A{
B b = new B();
}
//2)
class A{
B b;
{
b = new B();
}
}
what is the difference in initialization in these two ways ? Also if both the statement are in one single class , what would be their sequence of execution and why?
EDIT: Adding some more clarification:
class C{
//1)
int i = 5;
//initializers block
{
i =7;
}
}
What is the sequence of execution for both these two statements ? What is the final value of i ?
UPDATE FOR THE NEW CLEARER QUESTION:
It sees now that I should have added more text to my question. I
wanted to know what would be the sequence of execution in case both
these statements(1 and 2) are in one single class for the same
variable ?
You are interessted something like this:
private class Test {
public String field = new String("1");
{
field = new String("2");
}
}
At first the field get the value 1, after that the constructor will be called and the init block which was placed in the ctor at compile time will be executed so the value of field is "2".
See this example:
http://ideone.com/72uxES
See also this Question and answer:
Default constructor vs. inline field initialization
OLD VERSION
I think you mean something like this:
Object obj = new Object()
Or
Object obj;
{
obj = new Object();
}
The curly brackets define a scope in which the variable life time is given.
Say we have following example:
import java.util.*;
import java.lang.*;
import java.io.*;
class Ideone
{
private static void checkObject(Object obj) {
if (obj == null)
System.out.println("Object is null");
else
System.out.println("Object is not null");
}
public static void main (String[] args) throws java.lang.Exception
{
Object obj;
{
obj = new Object();
checkObject(obj);
}
checkObject(obj);
}
}
The Output is:
Object is not null
Object is not null
But if we change it to:
{
Object obj = new Object();
checkObject(obj);
}
checkObject(obj);
It will not even compile and give these error msg:
Main.java:22: error: cannot find symbol
checkObject(obj);
^
symbol: variable obj
location: class Ideone
1 error
The first declares a variable obj and initialize it inside the scope
because it was outside declared it can be used after the scope.
If it is declared and initialized only in the scope it can be used only inside the scope.
The lifetime is bound to the scope.
If you use the curly brackets to initialize class fields
you are able to use more than one statement to initialize them
but you can also simply create a final method and call the method to initialize the field.
Example for curly brackets and field initialization:
class A {
private String field;
{
StringBuilder builder = new StringBuilder("Text").append(value)
.append(" ")
.append(otherValue);
//make some computations
//append to builder
//add to field
field = builder.toString();
}
Hint:
The Java compiler copies initializer blocks into every constructor.
Therefore, this approach can be used to share a block of code between
multiple constructors.
See working example:
http://ideone.com/X42rQI
As you know that the constructor is called when we instantiate a class. Also all classes have top level Class as Object in JAVA. Now whenever we call the constructor of any class for your case A as new A() it leads us to call first super() leading to Object's constructor.
Now in your example1 your variable b is declared and initialised in the class itself. So before the constructor of class A is executed the variable b is initialised i.e. all the code that you write in public A() will be executed after b has been initialised.
In your example2 your variable b is declared in the class but is being initialised in the constructor of A. If you have some code before the line b = new B(); that code would be executed first then the b would be initialised.
See the example below :
Class A{
B b = new B();
public A(){
b == null; //FALSE as it has been already initialised.
}
}
But
Class A{
B b ;
public A(){
b == null; //TRUE as it has not been initialised.
b = new B();
b == null; //FALSE as it has been just initialised.
}
}
I assume it has to do with the following:
Initializing Instance Members
Normally, you would put code to initialize an instance variable in a
constructor. There are two alternatives to using a constructor to
initialize instance variables: initializer blocks and final methods.
Initializer blocks for instance variables look just like static
initializer blocks, but without the static keyword:
{
// whatever code is needed for initialization goes here
}
The Java compiler copies initializer blocks into every constructor.
Therefore, this approach can be used to share a block of code between
multiple constructors.
https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
Basically it means that all instance variables that are between the brackets will be initialized for all constructors. Even though your classes dont have multiple constructors
added example with multiple constructors
class A{
B b;
int index;
String result;
{
b = new B();
index = 0;
}
public A(int temp){
// nothing
}
public A(int temp, String test){
this.result = test;
}
public int getIndex(){
return index;
}
}
It doesnt matter here which constructor you use, as the initialization between the brackets is copied into both constructors. a.getIndex() will always return '0'
Related
I want to build a method that when it is called in main, automatically increment the value of variable.If first value is 0 when its called increment it to 1 , when I call for second time from 1 to be incremented at 2 and so on.
Notes: The method is part of a class and it called via object in main.
you can use the static variables. Static variables are initialized only once, at the start of the execution. These variables will be initialized first, before the initialization of any instance variables.
Create a static variable whose value can be updated in a function.
let this be your class
class Student {
static int b; //initialized to zero only when class is loaded not for each object created.
public void update(){
//incrementing static variable b
b++;
}
public void showData(){
System.out.println("Value of b = "+b);
}
}
and this be your main class
public class Demo{
public static void main(String args[]){
Student s1 = new Student();
s1.update();
s1.showData();
Student s2 = new Student();
s2.update();
s1.showData();
}
}
output:
Value of b = 1
Value of b = 2
Well, you kinda left a lot up for interpretation here, assuming the "value of variable" is part of the object the code would be something like this:
public class MyClass {
public int myVariable = 0;
public MyClass() {}
public void incrementMyVariable() {
myVariable++;
}
}
How you would handle this depends on where the variable your referring to is located ie. main method, object variable, etc... Additionally, if the variable needs to be kept constant across all the objects created for the class you would need it to be static.
Why can we do this:
class A{int a=5;}
but are not allowed to do this:
class A {
int a;
a=5;
}
just put it inside a block then.
class A {
int a;
{a=5;}
}
An initialization block will run every time you make in instance of the class e.g.
new A();
this is of course between two other initializations related to creating a new instance.
first is the field's initializations like when you declare a field with a value.
int a = 25;
then the block initialization
{
a = 5;
}
then the constructor:
A() {
a = 6;
}
This question already has answers here:
Polymorphism inside constructors in Java
(6 answers)
Closed 3 years ago.
i got a question in my Java test and i was wrong. please explain to me why.
public class A {
protected String str = "A";
public static int i = 1;
public A() {
foo();
}
public void foo() {
// TODO Auto-generated method stub
System.out.println(str + " " + i);
}
}
public class B extends A {
protected String str = "B";
public static int i = 2;
public B() {
foo();
}
public void foo() {
// TODO Auto-generated method stub
System.out.println(str + " " + i);
}
}
public class Program {
public static void main(String args[]){
A a = new B();
B b = new B();
}
}
in the test they asked me what is the output?
i answered : "A 1 B 2 A 1 B 2"
but the correct answer was : "null 2 B 2 null 2 B 2"
could you please explain why?
For the line A a = new B(); the output is null 2 B 2, because the instance fields in your class are not initialized until the implicit super() is finished running.
In this case since class B is extending the class A the B() constructor will implicitly call the super class no-arg constructor A() through super(), where the foo() method is called.
public A() { <---
foo(); //overriden version in class B is called |
} |
|
public B() { |
// Static fields are already initialized |
// Instance fields are not yet initialized |
// Here super() is called implicitly which calls A() ---
// Instance fields are now initialized to respective values
foo();
}
The overriden foo() of class B is called and as the foo() is overriden in class B, now since the super() is not yet finished the instance fields of class B is not initialized and is null. So you see the first null 2.
Then when the control comes out of super() the instance initializers are run for B and then foo() of class B is called at which point the instance fields of class B is initialized to the value B, so you see B 2 printed.
You don't see any issue for the static fields as because they don't depend on the super() call to finish, they are initialized when the class is loaded, so you see the value of i always initialized and printed instead of null.
Same is the case for the line B b = new B();.
An important thing to note is that you have redefined the str instance field in class B, so when the overriden foo() is invoked it will actually refer to the instance field of the class B rather than the field of class A.
Consider this code, where I removed the str field from class B:
class A {
protected String str = "A";
public static int i = 1;
public A() {
foo();
}
public void foo() {
// TODO Auto-generated method stub
System.out.println(str + " " + i);
}
}
class B extends A {
public static int i = 2;
public B() {
foo();
}
public void foo() {
// TODO Auto-generated method stub
System.out.println(str + " " + i);
}
}
This will print the output below when you re-run your program:
A 2
A 2
A 2
A 2
This is happening because the super() of B is calling the constructor A() which in turn is calling the Object() constructor through its own super(). Once the super() is done in A() the instance members of B inherited from A are all initialised. Now the overriden foo() will print out the initialised value of str inherited from A.
new B() will attempt to create a new instance of B, using B's constructor. All constructors always start with a super() call even if said call isn't there. Separate from that there are the 'instance initializers'; these are the expressions being assigned to the str variable. They are not string constants because that'd require a static final variable and str isn't.
Methods overload, but fields do not: Each class has its own field named str unrelated to the other one's str field.
The order of execution for object creation is as follows:
First, set all fields to initial value (null / 0 / false)
Run the super() call from the targeted constructor in B to figure out which constructor is intended for A(), along with the parameters required to call the constructor of the parent.
Invoke that superconstructor (which itself does this 5-step routine on its own stuff too!)
run all instance initializers in this class.
now continue and run the rest of the constructor.
So, in order:
A.str, B.str are both set to null.
A.str = "A" is evaluated.
A's constructor runs, and calls foo(). foo is a method, so dynamic dispatch is used; B overrides it, this is an instance of B, therefore, run B's foo(), not A's foo().
B's foo runs, and prints B's str which is still null.
B's foo prints its version of 'i', which is 2. Hence null 2
Now B.str = "B" is evaluated.
now the rest of B's constructor is run, which again runs B's foo(), but this time B.str has been initialized, so it prints B 2 instead.
Then we do it again; the type of the variable you assign the instance to has absolutely no effect here, so, null 2 B 2 prints a second time.
I'm pretty new to Java, as my post might give away.
I need to create a class (let's call it class A) which uses another class (class B) as one of its fields. Class A's constructor calls class B's constructor. So far things work fine.
But when one of A's methods tries to use one of B's methods on the object of class B, I get a NullPointerException. This is probably too confusing so I wrote this simple example which creates the Exception.
This is class B:
public class class_B {
private int y;
public class_B(int N) {
int y = N*N;
}
public int class_B_method() {
return y;
}
}
and this is class A:
public class class_A {
private class_B obj;
public class_A(int N) {
class_B obj = new class_B(N);
}
public int call_class_B_method() {
return obj.class_B_method();
}
public static void main(String[] args) {
int N =4;
class_A p = new class_A(N);
int a = p.call_class_B_method();
}
}
When I run class_A I get the exception on the line "int a = p.call_class_B_method();".
I don't understand this, since 'obj' should have been created by the constructor 'class_B' and should be available for the method 'call_class_B_method'.
thanks!
This line in the constructor of class_A
class_B obj = new class_B(N);
initializes a local variable obj, not the obj field. This local object class_B gets created, and then almost immediately discarded. Usually compilers warn you of situations like this, for two reasons - first, you have a local variable that "shadows" a field, and second, a local variable is assigned and then never used again.
Change your code to
obj = new class_B(N);
to fix the problem.
This line is wrong(because you lose the reference of the obj):
class_B obj = new class_B(N);
You should write:
obj = new class_B(N);
In the constructor of class_A you're not referencing the field obj, you're creating a new (local) variable with the same name. This is why the member never gets instantiated. You should write obj = new class_B(N) in the contructor.
There are several possible ways to mitigate such kind of errors:
Declare the field obj final, then the compiler will comlain if you don't instantiate it in the constructor. This of course only works when you don't want to change the field value later.
Always use this as identifier: this.obj = new class_B(N). This may clutter the code sometimes, so I guess this is a matter of taste.
Btw. by convention, Java class names always start with a capital letter. But this might be the case only for your example.
I have a Doubt
when we initialize our instance variables in Instance initialization block(s) in case of inheritance do they override the value of variable?
For example
class A{
int x;
}
class B extends A{
int x = 10;
}
public class C{
public static void main(String[] args){
A K = new B();
System.out.println(K.x);
}
}
o/p : 0
However when i use initialization blocks
class A{
int x;
{x = 15;}
}
class B extends A{
{x=20;}
}
public class C{
public static void main(String[] args){
A K = new B();
System.out.println(K.x);
}
}
OUTPUT 20
Why its so? why my initialization block(s) are affecting instance variables ? Moreover , i know that blocks are called when we make object but still the variable at output should correspond to variable type i.e A K (K should give value corresponding to class A)
You can override methods only, not variables. This code isn't "overriding" instance variables.
The first example has a different variables named x defined for A and B, making the variable an A means you see the variable defined for A (see the link provided by paulk23). In the second there is only one instance variable x which is visible to the subclass, the instance initializer assigns a value to an existing variable.
In the first example, you have two declarations of x, and in the second you only have one. In the second example, try changing B to:
class B extends A {
int x;
{ x=20; }
}
and you'll see the same behaviour as the first example: B defines a new variable that has an independent value from the one in A.