Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different behaviour of same statement while executing on JShell

I was working on a problem to store reference of two classes within each other

For Example:

class A {
B b;
A(B b){
this.b = b;}
}

class B {
A a;
B(A a){
this.a = a;}
}

public static void main(String...s){
A a = new A(new B(null));
a.b.a = a;
}

Now if instead of above initialisation, if I use below statement:

A a = new A(new B(a));

I got below error which is quite obvious:

Main.java:19: error: variable a might not have been initialised
        A a = new A(new B(a));

But if I try the same on JShell, it works just fine (Just to be extra sure that variable a has never been initialized, I checked for variable a just before executing the statement which confirms that it was not initialized before:

enter image description here

May be I am missing something here, but can some one please help me to understand why there are two different behaviours of the same statement being executed in JAVA.

A simple way to understand this problem is that below statement is allowed in Jshell but not in normal program:

var somevar = somevar;
like image 795
Aman Chhabra Avatar asked Dec 18 '22 00:12

Aman Chhabra


1 Answers

The statement A a = new A(new B(a)); is not the declaration of a local variable.

But first, the issue you're describing can be simplified to:

jshell> int a = a;
a ==> 0

Now, how did that work?

Well, as Snippets of JEP 222 says it:

In JShell, a "variable" is a storage location and has an associated type. A variable is created explicitly with a FieldDeclaration snippet:

int a = 42;

or implicitly by an expression (see below). Variables have a small amount of field semantics/syntax (for example, the volatile modifier is allowed). However, variables have no user-visible class enclosing them and will be generally viewed and used like local variables.

So, they behave a little like fields and a little like local variables.

Like a field, but unlike a local variable, a declaration without initializer will assign a default value, e.g.

jshell> int b;
b ==> 0

But, back to int a = a;. Section State of JEP 222 says:

The JShell state is held in an instance of JShell. A snippet is evaluated in a JShell with the eval(...) method, producing an error, declaring code, or executing a statement or expression. In the case of a variable with an initializer, both declaration and execution occur.

So, the declaration of the variable, and the execution of the initializer, are two separate actions.

This means that when the initializer is executed, the variable has already been declared, and has already been assigned the default value.

In effect, int a = a; is evaluated as:

jshell> int a;
a ==> 0

jshell> a = a;
a ==> 0

This is how the jshell REPL is designed to work. It is not a bug.

like image 90
Andreas Avatar answered Dec 28 '22 04:12

Andreas