Order of excecution, static blocks, fields - java

I know that static blocks are run before anything. But here, what happens when B.test() is called? Order of execution and setting of values? Later, when b1 is set to null, still how b1.i evaluates to 20?
class B
{
static int i;
static {
i = 20;
System.out.println("SIB");
}
static int test() {
int i = 24;
System.out.println(i);
return i;
}
}
public class Manager {
public static void main(String[] arg) {
B.test();
B b1 = null;
System.out.println(b1.i);
}
}
The output is:
SIB
24
20

The value of i here
static int i;
static {
i = 20;
System.out.println("SIB");
}
is set to 20 and never modified, so when you access b1.i, it's still 20.
In your test() method you are using another i variable that is not related to the static one.

i is static, so b1.i is equivalent to B.i. Just setting b1 to null doesn't change any static variables.
When B.test() is called, first the B class is loaded, and the static blocks are run. Next, B.test() creates a new method-local variable called i, which is completely different from B.i. This new, local i is printed and returned. No changes are made to B.i, and certainly not just because you created a new B object reference that was null -- that would never have any effect on anything.

But here, what happens when B.test() is called? Order of execution and setting of values?
There is no change.
Later, when b1 is set to null, still how b1.i evaluates to 20?
Because b1 isn't used, the field is static so you are actually using B.i

What happens is:
B.test() is called for the first time, before actually running it:
Class B is loaded,
Static initializer executed (B.i = 20 now)
Contents of B.test() method are executed
(creates a method-local int i = 24 (which shadows the static variable B.i) and prints it)
b1.i is interpreted as B.i (which is still 20) and it's printed.

What you did: What really happened:
B.test() - static block of class B is run, static i set to 20, SIB is displayed
- test method is called, local property i set to 24, 24 is displayed
b1 = null - set reference for b1 to null. Note that this doesn't change the value of class B's static properties
System.out.println(b1.i) - b1 is still Class B. It doesn't matter what its current reference is. Static i for class B is still 20, 20 is displayed

Related

Why there is need of return statement

I have very silly doubt that why we use return statement in method . Without using return statement in method we can also get required value
as example
package testing;
public class ReturnMethod {
static int a = 10;
static int b = 5;
static int c;
static int d;
public static void add() {
c = a + b;
}
public static int returnAddValue() {
d = a + b;
return d;
}
public static void main(String[] args) {
add();
System.out.println("c: " + c);
int value = returnAddValue();
System.out.println("value: " + value);
}
}
In above example in both the cases i am getting output
c: 15
value: 15
So i am having doubt when to use return statement and why is neccessary
With return statement, the return value is not necessary to be saved in any global, external or member variable.
However, without return statement you have to prepare kind of outer variable value to track that.
If you assign the result of a method to a static variable (and, indeed, pass in the "parameters" of the method by setting static variables), you have problems when that method is called by two threads concurrently, since the variables are shared for all invocations of the method:
Thread t1 = new Thread(() -> {a = 1; b = 2; add(); }); t1.start();
Thread t2 = new Thread(() -> {a = 3; b = 4; add(); }); t2.start();
t1.join(); t2.join();
You don't know which of these threads run first, or even if they run at the same time; so you don't know what the value of a or b is when you call add(), and nor do you know whether the value in c afterwards is the result of the invocation in the first or second thread (or a mixture of the two).
The value stored in c afterwards could be any of 3, 5 or 7 (or any other value, if there is another thread which is also invoking add() concurrently outside this code.
This problem of thread interference just completely goes away if you keep values localized to the stack, by passing a and b as method parameters, and receiving the result as a return value.
Even if your code is single-threaded, it's simply ugly to have to write:
a = 1;
b = 2;
add();
int result = c;
rather than
int result = add(1, 2);
You should use a return statement, when you need the method to return a value.
In your case, both methods work.
But you can, and should use returning methods, when you don't want a field of your class to be changed by another class.
For example, you want money to be only seen, and not changed, when you are making a bank-account related software. So, you make money private, and make a method which returns the money. In this way, other classes can only see money, but not change it.
First, your functions are different, as you see
public static **void** add()
public static **int** returnAddValue()
First one does not return anything, because it has void as return type and the second one has int as return type.
First one works, because c is a global variable.
You typically would use return when you don't store the result in a (static) variable of your class.
public class ReturnMethod {
static int a = 10;
static int b = 5;
public static void add() {
int c = a + b;
}
public static int returnAddValue() {
int d = a + b;
return d;
}
public static void main(String[] args) {
add();
//not possible to access c here
//System.out.println("c: " + c);
int value = returnAddValue();
System.out.println("value: " + value);
}
}
In that modified example, there would be no way for you to access the result of the add() method.
You should probably read about Scopes in Java.
You have a class variable c & d. These variables are associated with the class and stored in heap. If you assign a value back to it and you can access it without a explicit return statement. But if you have declared d inside the method then return statement is required to give the value back to the caller.
The reason that you are able to access the value of class variable c is that it has been initialized as static. Had this not been the case the information in the c variable would be lost as soon as the add method ends. The reason methods have return value is that they user can get the updated value , if there are any manipulation in the object data. In this case there is a very small, what if there is series of manipulation with the data. In that case the final value has to be returned to the calling object which without return statement is not possible.
Its totally depends upon our requirement whether to return a value from our method or update instance variable. Some time we just want to process a value and get back the result in and result will be used in different manner, in this case we need to return value from method.
For example
java.lang.Math.sqrt(double a) method return a value and we use returned value as per our need OR requirement. Can you think if this method does not returned any value then what it should update, I think this method useless if it does not returned any value.
The variable C in your code snippet is accessed in the class throughout, and will stay until the object of the class exists. So you can print the value of Variable C outside the method.
However, if you had declared a local variable in the method add(), then print statement System.out.println("c: " + c); will print the default value for variable c. That is zero in this case.

Why should data fields be static and final

Deitel's How To Program Java book says:
A final field should also be declared static if it is initialized in its declaration to a value.
Why is that?
public class A
{
private final int x = 5;
private static final int y = 5;
}
I think x and y are the same.
What does the static qualifier matter here?
What is the advantage of the static qualifier up there for software engineering observation?
x is an instance variable while y is global.
What does that mean?
Let's look at this example:
public class A {
public A() {
System.out.println("create A");
}
}
public class B {
public B() {
System.out.println("create B");
}
}
public class C {
private static B b = new B();
private A a = new A();
}
Then a main:
public static void main(String[] args) {
C c1 = new C();
C c2 = new C();
}
Which prints:
> create B
> create A
> create A
c1 and c2 shares the same instance of B while they both create their own instance of A!
So c1.b == c2.b while c1.a != c2.a.
So summary:
there is only one and the same place/address for field b for every instance of class C (c1, c2)
but for field a there are different places/addresses in the different instances.
The example is a bit oversized with class A and B:
Even for simple fields (int, float, ...) is one and the same place/occurrence for a static field in every instance of a class.
Since it is final, it will always hold the same value.
If you don't declare it static, you will create one variable for each instance of your class. Being static means you declare the variable only once, avoiding unnecessary memory usage.
Declaring a variable as static is more memory effecient. In your example for instance, no matter how many times you create a new A(), because fields x and fields y have been declared static, they will only be allocated memory once. If you do not declare them as static, they will be allocated memory with every new class instance.
It is sensible to declare a final variable that has been initialized like yours as static because it is not able to change, and thus allocating it memory just one time is acceptable.
Essentially, it's to save memory. If the constant is always the same no matter what, then you might as well make it static so that it doesn't get created for each object. You don't want to make it static, however, if the constant is not necessarily the same for each object (for example, if your constant is initialized somewhere in a constructor).
It saves memory as it only allocates for 1 copy of the variable. If you were to make a new instance for a non-static variable for it will make a new copy for that specified instance.
Since they are final they cannot be changed so it would make sense to make them static, so when you make new instances, nothing new is allocated for the variables since they can't even be altered.

Why attempt to print uninitialized variable does not always result in an error message

Some may find it similar to the SO question Will Java Final variables have default values? but that answer doesn't completely solve this, as that question doesn't directly print the value of x within instance initializer block.
The problem arises when I try to print x directly inside the instance initializer block, while having assigned a value to x before the end of the block :
Case 1
class HelloWorld {
final int x;
{
System.out.println(x);
x = 7;
System.out.println(x);
}
HelloWorld() {
System.out.println("hi");
}
public static void main(String[] args) {
HelloWorld t = new HelloWorld();
}
}
This gives a compile time error stating that variable x might not have been initialized.
$ javac HelloWorld.java
HelloWorld.java:6: error: variable x might not have been initialized
System.out.println(x);
^
1 error
Case 2
Instead of directly printing, I am calling a function to print:
class HelloWorld {
final int x;
{
printX();
x = 7;
printX();
}
HelloWorld() {
System.out.println("hi");
}
void printX() {
System.out.println(x);
}
public static void main(String[] args) {
HelloWorld t = new HelloWorld();
}
}
This compiles correctly and gives output
0
7
hi
What is the conceptual difference between the two cases?
In the JLS, §8.3.3. Forward References During Field Initialization, its stated that there's a compile-time error when:
Use of instance variables whose declarations appear textually after the use is sometimes restricted, even though these instance variables
are in scope. Specifically, it is a compile-time error if all of the
following are true:
The declaration of an instance variable in a class or interface C appears textually after a use of the instance variable;
The use is a simple name in either an instance variable initializer of C or an instance initializer of C;
The use is not on the left hand side of an assignment;
C is the innermost class or interface enclosing the use.
The following rules come with a few examples, of which the closest to yours is this one:
class Z {
static int peek() { return j; }
static int i = peek();
static int j = 1;
}
class Test {
public static void main(String[] args) {
System.out.println(Z.i);
}
}
Accesses [to static or instance variables] by methods are not checked in this way, so the code above produces output 0, because the variable initializer for i uses the class method peek() to access the value of the variable j before j has been initialized by its variable initializer, at which point it still has its default value (§4.12.5 Initial Values of Variables).
So, to summarize, your second example compiles and executes fine, because the compiler does not check if the x variable was already initialized when you invoke printX() and when printX() actually takes place at Runtime, the x variable will be assigned with its default value (0).
Reading the JLS, the answer appears to be in section 16.2.2:
A blank final member field V is definitely assigned (and moreover is not definitely unassigned) before the block (§14.2) that is the body of any method in the scope of V and before the declaration of any class declared within the scope of V.
This means that when a method is called, the final field is assigned to its default value 0 before invoking it, so when you reference it inside the method, it compiles successfully and prints the value 0.
However, when you access the field outside of a method, it is considered unassigned, hence the compilation error. The following code will also not compile:
public class Main {
final int x;
{
method();
System.out.println(x);
x = 7;
}
void method() { }
public static void main(String[] args) { }
}
because:
V is [un]assigned before any other statement S of the block iff V is [un]assigned after the statement immediately preceding S in the block.
Since the final field x is unassigned before the method invocation, it is still unassigned after it.
This note in the JLS is also relevant:
Note that there are no rules that would allow us to conclude that V is definitely unassigned before the block that is the body of any constructor, method, instance initializer, or static initializer declared in C. We can informally conclude that V is not definitely unassigned before the block that is the body of any constructor, method, instance initializer, or static initializer declared in C, but there is no need for such a rule to be stated explicitly.
The difference is that in the first case you are calling System.out.println from initializer block so the block which is invoked before constructor. In the first line
System.out.println(x);
variable x is not yet initialized so that you get compilation error.
But in the second case you call instance method which doesn't know if variable has already been initialized so you don't have compilation error and you can see the default value for x
Ok, here is my 2 cents.
We all know that final variables can be initialized only While declaring or later on in constructors. Keeping that fact in mind, let see what happened here so far.
No errors Case:
So when you use inside a method, it have already a value.
1) If you initialize it, that value.
2) If not, the default value of data type.
Error case :
When you do that in an initialization block, which you are seeing errors.
If you look at the docs of initialization block
{
// whatever code is needed for initialization goes here
}
and
The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors.
In compiler's eye, your code is literally equals to
class HelloWorld {
final int x;
HelloWorld() {
System.out.println(x); ------------ ERROR here obviously
x = 7;
System.out.println(x);
System.out.println("hi");
}
public static void main(String[] args) {
HelloWorld t = new HelloWorld();
}
}
You are using it before even initializing it.
Case 1 :
Gives you a compile-error,
Because at System.out.println(x);
you are trying to print x which was never initialized.
Case 2:
Works because you are not directly using any literal values, instead you are calling some method, which is correct.
General Rule is,
If you are trying to access any variable which is never initialized
then it will give a compilation error.
We deal here with initializer block. The Java compiler copies initializer blocks into every constructor.
The compiler error don't occure in second example, because printing x is in another Frame, please refer to spec.

Order in which static variables and methods are declared/called

I am reading a book about Java. It gives an example like this:
class UseStatic {
static int a = 3;
static int b;
// ... some more lines
static {
b = 4 * a;
}
}
Then it explains this:
As soon as the UseStatic class is loaded, all the static
statements are run. First, a is set to 3, then the static block
executes, ..., and then initializes b to a*4 or 12.
I wonder what really happens here with the order in which the lines are excecuted. How can it first start at the top at static int a = 3 to only then jump over static int b to static {..} to only then jump back to static int b? How does it know this dependency?
It doesn't "jump over static int b", and it doesn't "jump back to static int b." There is nothing to "jump back" to because static int b is only a declaration, not an initialization/assigment. It declares the variable but does not assign it a value.
First a is declared and initialized. Then b is declared. Then the static block is executed, which assigns a value to b.
The Java Language Specification dictates the exact order of all of these things. See Jon Skeet's answer to Are there any guarantees in JLS about order of execution static initialization blocks? for more.

Why is this Java code in curly braces ({}) outside of a method?

I am getting ready for a java certification exam and I have seen code LIKE this in one of the practice tests:
class Foo {
int x = 1;
public static void main(String [] args) {
int x = 2;
Foo f = new Foo();
f.whatever();
}
{ x += x; } // <-- what's up with this?
void whatever() {
++x;
System.out.println(x);
}
}
My question is ... Is it valid to write code in curly braces outside a method? What are the effects of these (if any)?
Borrowed from here -
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.
You may also wanna look at the discussions here.
This is an initializer block that is executed while the instance of the class is being loaded/created and that is used to initialize member properties of a class (See Java http://download.oracle.com/javase/tutorial/java/javaOO/initial.html). You can have as many blocks as you want and they will be instantiated from top to bottom.
In addition to the instance block, you can have as many static blocks as you want as well to initialize static members. They would be declared as follows:
public class Initialization {
static int b = 10;
int a = 5;
static {
b = -9;
}
{
a += 2;
}
public static void main(String[] args) throws Exception {
System.out.println(ClientVoting.b);
System.out.println(new ClientVoting().a);
System.out.println(ClientVoting.b);
System.out.println(new ClientVoting().a);
}
static {
b = 1;
}
{
a++;
}
}
While the class is being initialized, the static member "b" is initialized as 10, then the first static scope changes its value to -9, and later to 1. This is only executed once while the class is loaded. This executes before the initialization of the first line of the main method.
On the other hand, the similar example to your class is the instance reference "a". A is initialized as 5, then the instance block updates it to 7, and the last block to 8. As expected, the static members are only initialized once in this code, while the instance blocks are executed EVERY time you create a new instance.
The output to this example is 1 8 1 8
It's an initializer block. It's used to set instance variables. The motivation to use initializer blocks over constructors is to prevent writing redundant code. The Java compiler copies the contents of the block into each constructor.

Categories