Constants and inner classes

瘦欲@ 提交于 2021-02-05 05:27:45

问题


  1. static variables in inner classes: inner class cannot contain static fields. It cannot contain static members, because there would be problem where to assign static member. Inner class is connected with outer class. I understand why it does not contain static member, but inner class can contain static constant. Why? Is it specially treated? Is it on special heap? Still it is static member, but constant, so it is specially treated?

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

  2. I wonder why variables of the method used in local class should 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
        }
      }
    }
    

    The answer is: variable x id copied to class A. It cannot be changed, because then there appeared inconsistency. So why the architects of Java did not create language where variable x is not copied? The address of the variable would be passed and then variable x would be changed without inconsistency. Can somebody give me example and explain this?

    Or issue connected with synchronization. Both variables should be the same, but what if we are out of the scope? One of the variables does not exits, so what with synchronization?

Edit: Why this works:

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 = a.g();
        }

        in1.f1(); //class A does not exists any more, field 'variable' is changed, despite it does not exist
    }

Why there is no synchronization problem?


回答1:


To answer your first question:

Personally, I don't see yet why it doesn't accept non-final static members in inner classes. However, I can tell you what happens on compile time. When you declare a static final primitive member, it can be compiled into the code that uses this member. However, when you try to create a static final Object o = new Object();, it cannot know on compile time what the o will be pointing at. And obviously gives the same compiler error as if you create a static int (non-final) in your inner-class.

To answer the second question, here is why:

x is a local variable, which is pushed onto the stack. When you use a reference to x in your inner class, you will have problems. Because the inner class is most likely going to live longer than the scope of that function. As soon as the function ends, x goes out of scope and gets removed from the stack. So, right now, your inner class still has a reference to a variable that doesn't exist anymore. So, this is a little trick implemented in the compiler: if you declare your x as final the compiler knows it won't change, so there is no point of keeping a reference to it. This allows the compiler to copy x into the instance of inner class as a new member. Thus, x will be copied to the heap. Compare this to the invalid reference to the stack if you do not mark it as final (which doesn't compile of course, because the compiler protects you of making this mistake).




回答2:


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

  1. After complilation inner class is no different from top level class, only all of its constructors get additional parameter - a reference 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;
    }
}

no reasons why X$Y cannot have static members. Syntax is not a problem too

class X {
    class Y {
        static int x = 1;
    }

    void x() {
         Y.x = 2;
    }
}

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

  1. final var gets to anonymous class as a 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 why outer variable has to be final is because otherwise it would look like we can change it from inner class code

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

but it is not true because inner class works with a copy




回答3:


  1. The idea behind inner classes is that they belong to an instance of the containing class. A static member of the inner class would therefore be equivalent to a non-static member of the containing class, if we ignore scoping and details like that.

    However, with the way inner classes are implemented this is impossible to achieve: the inner class is compiled into an independent class, and if it had static members they would be shared between all instances of the containing class. This breaks the illusion that the language is trying to create. Therefore static members are forbidden altogether.

    The only exception to this rule are fields that are declared as static final and are initialized with compile-time constants, such as integer or string literals. These can be allowed because compile-time time constants would be shared between all instances of the containing class anyway.

  2. The address of the local variable is useless once the variable goes out of scope, for example when the method returns. What should happen if the variable is read or written then? The address now points to an illegal memory location, or even worse: to a completely unrelated variable.



来源:https://stackoverflow.com/questions/18156543/constants-and-inner-classes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!