Constants and inner classes

  • static variables in inner classes: inner class cannot contain static fields. It cannot contain static members because there will be a problem with assigning a static member. The inner class is associated with the outer class. I understand why it does not contain a static member, but the inner class may contain a static constant. What for? Is this a special treatment? Is it on a special heap? Nonetheless, it is a static member, but persistent, so is it specially processed?

    It may contain: "final static int x", but not "static int x".

  • I wonder why the method variables used in the local class must be final . I mean:

     public void function1() { final int x; // value of x, which is used in class A have to be final class A { void function2() { //body of function } } } 

    Answer: the variable x id copied to class A. It cannot be changed, because then inconsistency arose. So why didn't the Java architects create a language where the variable x is not copied? The address of the variable will be passed, and then the variable x will be changed without inconsistency. Can someone give me an example and explain this?

    Or a sync issue. Both variables should be the same, but what if we get out of scope? One of the variables does not come out, so what about synchronization?

Edit: Why does this work:

 interface In { void f1(); } class A { int variable = 3; In g() { return new In() { @Override public void f1() { variable = 6; System.out.println(variable); } }; } } public static void main(String[] args) { In in1; { A a = new A(); in1 = ag(); } in1.f1(); //class A does not exists any more, field 'variable' is changed, despite it does not exist } 

Why is there no synchronization problem?

+4
source share
3 answers

To answer your first question:

Personally, I still do not see why it does not accept non-static static members in inner classes. However, I can tell you what happens at compile time. When you declare a static final member primitive , you can compile it into code that uses this element. However, when trying to create a static final Object o = new Object(); it cannot know at compile time what o points to. And, obviously, it gives the same compiler error, as if you created a static int (not finite) in your inner class.

To answer the second question, here's why:

x is a local variable that is pushed onto the stack. When you use the x reference in your inner class, you will have problems. Because the inner class is likely to live longer than the scope of this function. As soon as the function ends, x goes out of scope and is removed from the stack. So, right now, your inner class is still referencing a variable that no longer exists. So, this is a small trick implemented in the compiler: if you declare your x as final , the compiler knows that it will not change, so it makes no sense to refer to it. This allows the compiler to copy x into an instance of the inner class as a new member. This way x will be copied to the heap. Compare this with an invalid stack reference unless you mark it as final (which, of course, does not compile because the compiler protects you from this error).

+3
source

In my opinion, there are no unsolvable problems due to which inner classes cannot have static members, and the vars used in anonymous classes should only be final. I think it was just the decision of language designers.

  • After complication, the inner class does not differ from the top-level class, only all its constructors receive an additional parameter - a link to the outer class.

    class X {class Y {}}

Compiler

turns it into this

 class X { } class X$Y { private final X x; X$Y(X x) { this.x = x; } } 

there is no reason why X $ Y cannot have static members. Syntax is not a problem either.

 class X { class Y { static int x = 1; } void x() { Yx = 2; } } 

as for static final int x = 1; different from static int x = 1; - the difference is that the former does not need initialization, it is a constant, and the latter requires an implicit static initialization block to place the code that will assign 1 x.

  • final var goes into an anonymous class as constructor parameter

class X {void x () {final Integer x = 1; new Runnable () {public void run () {int y = x; }}; }}

actual anonymous class

 class X$1 { private final Integer x; X$1(Integer x) { this.x = x; } ... 

the only reason the external variable should be final is that otherwise it would look like we can change it from the internal code of the class

 void x() { Integer x = 1; new Runnable() { public void run() { x = 2; } ... 

but this is not so, because the inner class works with a copy

+1
source
  • The idea of ​​inner classes is that they belong to an instance of the containing class. Thus, the static member of the inner class will be equivalent to the non-stationary member of the containing class if we do not consider the scope and such details.

    However, since inner classes are implemented, this cannot be achieved: the inner class is compiled into an independent class, and if it has static members, they will be shared between all instances of the containing class. This violates the illusion that language is trying to create. Therefore, static elements are generally prohibited.

    The only exceptions to this rule are fields declared as static final , and are initialized by compile-time constants, such as integer or string literals. They can be resolved, since compile-time constants will be shared by all instances of the containing class.

  • The address of a local variable is useless as soon as the variable goes out of scope, for example, when a method returns. What happens if a variable is read or written? Now the address indicates an illegal memory location or, even worse: a completely unrelated variable.

+1
source

Source: https://habr.com/ru/post/1496250/


All Articles