Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does int p = (p=1) + p; fail in field definitions but is OK within method?

Tags:

java

class Test{

    int p = (p=1) + p;   // ERR "Cannot reference a field before it is defined"
    int q = (q=1) + this.q; //fine!

    void f() {
        int t = (t=1) + t; // fine!
    }       
}

In the first case I understand that: when assignment (or subsequent addition?) is performed, p is treated as not declared.

But why is it different within a method? OK t is not treated as uninitialized because (t=1) is performed before addition. OK, t is not a field, but it is also not declared at the moment!

Can I understand it somehow? Or I shall just memorize this difference?

Maybe this is also related a bit to the same:

    static int x = Test.x + (x=1) + Test.x; // produces 2

    void f() {
       int y = y + (y=1) + y;  // ERR  local variable y may not have been initialized
   }

Why 2? First (x=1) is somehow evaluated (x is not declared!!!), then it returns 1, now x is already assigned (!?) and contains 1, so both Test.x is 1, but (x=1) operator also returned 1 so result shall be 1 + 1 + 1 and 3 shall be (reassigned) into x as a result of evaluating Test.x + (x=1) + Test.x expression.

PARTIAL ANSWER: Actually, the results are implementation specific. JLS guarantees only the order in which operands of a binary operator are evaluated (left-to-right). But if we have binary operators (say, plus) with same priority, their order of evaluation is NOT guaranteed. In my case plus operators are evaluated left-most first, this is why static "int x = Test.x (ZERO) + (x=1) + Test.x (IS 1 after (x=1));" is 0 + 1 + 1 (remember, x=1 is an operator that returns assigned value). Again in my case within method "int y = y + (y=1) + y;" leftmost plus operator is evaluated first (giving error), but if JVM chose to evaluate second plus operator first, then it is guaranteed to evaluate its left operand first and (y=1) would make the y variable initialized (so the code would compile!)

I am still not sure why (x=1) is not treated as undeclared with fields. I vaguely remember that JLS allows undeclared variable in LHS (so any assignment works), but not in RHS (x++, int sth=x). I can memorize it using the following snippet:

class Test {

    { x = 7; }  // fine! Initializer is like a regular method
    int x;

    static { y = 7; }  // fine! Initializer is like a regular method
    static int y;

P.S. This is surely not a duplicate of Default Values and Initialization in Java - there is no direct explanation there. Here we need not only default values (zero for int) rules, but a lot of different rules in a very COMPLEX combination (operator precedence, and especially some rare peculiarities of assignment!). Also I know that assignment precedence is lowest here and that assignment is an operator and it returns value!

like image 335
Code Complete Avatar asked Jul 11 '19 17:07

Code Complete


People also ask

What is superclass and subclass in C++?

Sub Class: The class that inherits properties from another class is called Sub class or Derived Class. Super Class:The class whose properties are inherited by sub class is called Base Class or Super class.

WHAT IS &N in C?

&n writes the address of n . The address of a variable points to the value of that variable.

What is inheritance in OOP?

Inheritance in OOP = When a class derives from another class. The child class will inherit all the public and protected properties and methods from the parent class. In addition, it can have its own properties and methods. An inherited class is defined by using the extends keyword.

How many functions can be used in C program?

There are two types of function in C programming: Standard library functions. User-defined functions.

What does *P = null mean in C?

The statement int *p = NULL; is the same as writing: int *p; p = NULL; int * is the type. Basically, when you write: if (p != NULL) you are simply testing if p points to a place such that it is safe to use *p.

Why can't I check if *P = null?

The reason why you don't check if *p != NULL is because that would be testing if what it points to is NULL, and not test if the pointer itself is NULL. Of course you can choose to test *p against any value you like provided it is a valid pointer... It all depends on what you want to do. You didn't assign NULL to *p, you assigned it to p.

What is the meaning of *P in C++?

For int (*p) [3]: Here “p” is the variable name of the pointer which can point to an array of three integers. Below is an example to illustrate the use of int (*p) [3]: For int *p [3]: Here “p” is an array of the size 3 which can store integer pointers.

What is int () function in Python?

int () function in Python. int () function in Python and Python3 converts a number in given base to decimal.


1 Answers

Read on scope of local variable declarations in Java Language Specification. Your exact problem is described in Example 6.3-2. The description is this:

The following program causes a compile-time error because the initialization of local variable p is within the scope of the declaration of local variable p, but the local variable p does not yet have a value and cannot be used.

like image 90
Andrius Burokas Avatar answered Nov 10 '22 12:11

Andrius Burokas