Forward referencing is allowed during declarations when the undeclared variable is used in the LHS of an expression, but not if its in the RHS. Therefore, the following won't work :

class A
{
   int a=h;
   int h;
}

But the following code works :

class A
{
   int a=this.h;
   int h;
}

This will assign 0 to a as 0 is the default value of ints. Why did this work ? this refers to the present object, and it is being currently constructed. Why does the use of this make any difference ?

Recommended Answers

All 7 Replies

Come on guys! This is a really good question! I certainly want to know the answer.

That is really interesting. Here's the output from javap for two compiles. The first with the forward reference and the second without. Can't see any difference in what javap outputs.

class ForwardRefTest {
//   int a = this.h;    // for first compile
   int h;
   int a = h;           // for second compile
}
/*

D:\JavaDevelopment\Testing\ForumQuestions3>javap -c -verbose ForwardRefTest
Compiled from "ForwardRefTest.java"
class ForwardRefTest extends java.lang.Object
  SourceFile: "ForwardRefTest.java"
  minor version: 0
  major version: 50
  Constant pool:
const #1 = Method       #5.#18; //  java/lang/Object."<init>":()V
const #2 = Field        #4.#19; //  ForwardRefTest.h:I
const #3 = Field        #4.#20; //  ForwardRefTest.a:I
const #4 = class        #21;    //  ForwardRefTest
const #5 = class        #22;    //  java/lang/Object
const #6 = Asciz        a;
const #7 = Asciz        I;
const #8 = Asciz        h;
const #9 = Asciz        <init>;
const #10 = Asciz       ()V;
const #11 = Asciz       Code;
const #12 = Asciz       LineNumberTable;
const #13 = Asciz       LocalVariableTable;
const #14 = Asciz       this;
const #15 = Asciz       LForwardRefTest;;
const #16 = Asciz       SourceFile;
const #17 = Asciz       ForwardRefTest.java;
const #18 = NameAndType #9:#10;//  "<init>":()V
const #19 = NameAndType #8:#7;//  h:I
const #20 = NameAndType #6:#7;//  a:I
const #21 = Asciz       ForwardRefTest;
const #22 = Asciz       java/lang/Object;

{
int a;


int h;


ForwardRefTest();
  Code:
   Stack=2, Locals=1, Args_size=1
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   aload_0
   6:   getfield        #2; //Field h:I
   9:   putfield        #3; //Field a:I
   12:  return
  LineNumberTable:
   line 1: 0
   line 2: 4
  LocalVariableTable:
   Start  Length  Slot  Name   Signature
   0      13      0    this       LForwardRefTest;

}

D:\JavaDevelopment\Testing\ForumQuestions3>javap -c -verbose ForwardRefTest
Compiled from "ForwardRefTest.java"
class ForwardRefTest extends java.lang.Object
  SourceFile: "ForwardRefTest.java"
  SourceDir: length = 0x2
   00 1A
  minor version: 3
  major version: 45
  Constant pool:
const #1 = Asciz        Code;
const #2 = Asciz        SourceFile;
const #3 = Asciz        SourceDir;
const #4 = Asciz        ConstantValue;
const #5 = Asciz        Exceptions;
const #6 = Asciz        LineNumberTable;
const #7 = Asciz        LocalVariableTable;
const #8 = Asciz        ForwardRefTest;
const #9 = class        #8;     //  ForwardRefTest
const #10 = Asciz       java/lang/Object;
const #11 = class       #10;    //  java/lang/Object
const #12 = Asciz       ()V;
const #13 = Asciz       <init>;
const #14 = NameAndType #13:#12;//  "<init>":()V
const #15 = Method      #11.#14;        //  java/lang/Object."<init>":()V
const #16 = Asciz       I;
const #17 = Asciz       h;
const #18 = NameAndType #17:#16;//  h:I
const #19 = Field       #9.#18; //  ForwardRefTest.h:I
const #20 = Asciz       a;
const #21 = NameAndType #20:#16;//  a:I
const #22 = Field       #9.#21; //  ForwardRefTest.a:I
const #23 = Asciz       this;
const #24 = Asciz       LForwardRefTest;;
const #25 = Asciz       ForwardRefTest.java;
const #26 = Asciz       D:\JavaDevelopment\Testing\ForumQuestions3\;

{
int h;


int a;


ForwardRefTest();
  Code:
   Stack=2, Locals=1, Args_size=1
   0:   aload_0
   1:   invokespecial   #15; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   aload_0
   6:   getfield        #19; //Field h:I
   9:   putfield        #22; //Field a:I
   12:  return
  LineNumberTable:
   line 4: 4
  LocalVariableTable:
   Start  Length  Slot  Name   Signature
   0      13      0    this       LForwardRefTest;

}
*/
Member Avatar for coil

This is just a guess, but the first one doesn't work because the compiler doesn't know what h is. The second one works because when you call this, the compiler scans "this" to see if there is an variable h.

The current Language Reference has this to say:

8.3.2.3 Restrictions on the use of Fields during Initialization
The declaration of a member needs to appear textually before it is used only if the member is an instance (respectively static) field of a class or interface C and all of the following conditions hold:

The usage occurs in an instance (respectively static) variable initializer of C or in an instance (respectively static) initializer of C.
The usage is not on the left hand side of an assignment.
The usage is via a simple name.
C is the innermost class or interface enclosing the usage.

A compile-time error occurs if any of the four requirements above are not met.

What's interesting is that the third condition (via a simple name), which is the one that answers this question, was not present in earlier versions (eg JDK 1.4.2) of the same documentation. Did they change the language, or did they just notice this behaviour?

8.3.2.3 Restrictions on the use of Fields during Initialization
The declaration of a member needs to appear textually before it is used only if the member is an instance (respectively static) field of a class or interface C and all of the following conditions hold:

The usage occurs in an instance (respectively static) variable initializer of C or in an instance (respectively static) initializer of C.
The usage is not on the left hand side of an assignment.
The usage is via a simple name.
C is the innermost class or interface enclosing the usage.

A compile-time error occurs if any of the four requirements above are not met.

Thanks a lot. Can you please explain the 4th condition ?

Have a look at the language ref 8.3.2.3 - the bit I quoted is followed by loads of examples illustrating each of those points.

Thanks

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.