为什么Java禁止内部类中的静态字段?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1953530/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 01:45:21  来源:igfitidea点击:

Why does Java prohibit static fields in inner classes?

javainner-classesstatic-members

提问by Jichao

class OuterClass {
 class InnerClass {
  static int i = 100; // compile error
  static void f() { } // compile error
 }
} 

Although it's not possible to access the static field with OuterClass.InnerClass.i, if I want to record something that should be static, e.g. the number of InnerClass objects created, it would be helpful to make that field static. So whydoes Java prohibit static fields/methods in inner classes?

虽然无法使用 访问静态字段OuterClass.InnerClass.i,但如果我想记录一些应该是静态的内容,例如创建的 InnerClass 对象的数量,使该字段成为静态会很有帮助。那么为什么Java禁止内部类中的静态字段/方法呢?

EDIT: I know how to make the compiler happy with static nested class (or static inner class), but what I want to know is why java forbids static fields/methods inside inner classes (or ordinary inner class) from both the language design and implementation aspects, if someone knows more about it.

编辑:我知道如何让编译器对静态嵌套类(或静态内部类)感到满意,但我想知道的是为什么 java 禁止在语言设计和内部类(或普通内部类)中使用静态字段/方法实施方面,如果有人了解更多的话。

采纳答案by Gregory Pakosz

The idea behind inner classes is to operate in the context of the enclosing instance. Somehow, allowing static variables and methods contradicts this motivation?

内部类背后的想法是在封闭实例的上下文中操作。不知何故,允许静态变量和方法与这个动机相矛盾?

8.1.2 Inner Classes and Enclosing Instances

An inner class is a nested class that is not explicitly or implicitly declared static. Inner classes may not declare static initializers (§8.7) or member interfaces. Inner classes may not declare static members, unless they are compile-time constant fields (§15.28).

8.1.2 内部类和封闭实例

内部类是未显式或隐式声明为静态的嵌套类。内部类不能声明静态初始值设定项(第 8.7 节)或成员接口。内部类不能声明静态成员,除非它们是编译时常量字段(第 15.28 节)。

回答by Asaph

InnerClasscannot have staticmembers because it belongs to an instance (of OuterClass). If you declare InnerClassas staticto detach it from the instance, your code will compile.

InnerClass不能有static成员,因为它属于(的OuterClass)实例。如果声明InnerClassstatic从实例中分离它,你的代码进行编译。

class OuterClass {
    static class InnerClass {
        static int i = 100; // no compile error
        static void f() { } // no compile error
    }
}

BTW: You'll still be able to create instances of InnerClass. staticin this context allows that to happen without an enclosing instance of OuterClass.

顺便说一句:您仍然可以创建InnerClass. static在这种情况下,允许在没有封闭实例的情况下发生这种情况OuterClass

回答by OscarRyz

what I want to know is why java forbids static fields/methods inside inner classes

我想知道的是为什么java禁止内部类中的静态字段/方法

Because those inner classes are "instance" inner classes. That is, they are like an instance attribute of the enclosing object.

因为这些内部类是“实例”内部类。也就是说,它们就像封闭对象的实例属性。

Since they're "instance" classes, it doesn't make any sense to allow staticfeatures, for staticis meant to work without an instance in the first place.

由于它们是“实例”类,因此允许static功能没有任何意义,因为static首先意味着没有实例就可以工作。

It's like you try to create a static/instance attribute at the same time.

就像您尝试同时创建静态/实例属性一样。

Take the following example:

以下面的例子为例:

class Employee {
    public String name;
}

If you create two instances of employee:

如果您创建两个员工实例:

Employee a = new Employee(); 
a.name = "Oscar";

Employee b = new Employee();
b.name = "jcyang";

It is clear why each one has its own value for the property name, right?

很明显为什么每个人都有自己的财产价值name,对吗?

The same happens with the inner class; each inner class instance is independent of the other inner class instance.

内部类也是如此;每个内部类实例都独立于另一个内部类实例。

So if you attempt to create a counterclass attribute, there is no way to share that value across two different instances.

因此,如果您尝试创建counter类属性,则无法在两个不同的实例之间共享该值。

class Employee {
    public String name;
    class InnerData {
        static count; // ??? count of which ? a or b? 
     }
}

When you create the instance aand bin the example above, what would be a correct value for the static variable count? It is not possible to determine it, because the existence of the InnerDataclass depends completely on each of the enclosing objects.

当您创建实例时ab在上面的示例中,静态变量的正确值是count多少?无法确定它,因为InnerData类的存在完全取决于每个封闭对象。

That's why, when the class is declared as static, it doesn't need anymore a living instance, to live itself. Now that there is no dependency, you may freely declare a static attribute.

这就是为什么当类被声明为 时static,它不再需要一个活的实例来活自己。现在没有依赖了,你可以自由地声明一个静态属性。

I think this sounds reiterative but if you think about the differences between instance vs. class attributes, it will make sense.

我认为这听起来是重复的,但如果您考虑实例与类属性之间的差异,这将是有道理的。

回答by vmolchanov

Actually, you can declare static fields if they are constants and are written in compile time.

实际上,如果静态字段是常量并且是在编译时编写的,则可以声明它们。

class OuterClass {
    void foo() {
        class Inner{
            static final int a = 5; // fine
            static final String s = "hello"; // fine
            static final Object o = new Object(); // compile error, because cannot be written during compilation
        }
    }
}

回答by ianos

Here is the motivation that I find best suitable for this "limit": You can implement the behavior of a static field of an inner class as an instance field of the outer object; So you do not needstatic fields/methods. The behaviour I mean is that all inner class instances of some object share a field(or method).

这是我认为最适合此“限制”的动机:您可以将内部类的静态字段的行为实现为外部对象的实例字段; 所以你不需要静态字段/方法。我的意思是,某个对象的所有内部类实例共享一个字段(或方法)。

So, suppose you wanted to count all the inner class instances, you would do:

因此,假设您想计算所有内部类实例,您可以这样做:

public class Outer{
    int nofInner; //this will count the inner class 
                  //instances of this (Outer)object
                  //(you know, they "belong" to an object)
    static int totalNofInner; //this will count all 
                              //inner class instances of all Outer objects
    class Inner {
        public Inner(){
            nofInner++;
            totalNofInner++;
        }
    }
}

回答by Chochos

I guess it's for consistency. While there doesn't seem to be any technical limitation for it, you wouldn't be able to access static members of the internal class from the outside, i.e. OuterClass.InnerClass.ibecause the middle step is not static.

我想这是为了一致性。虽然它似乎没有任何技术限制,但您将无法从外部访问内部类的静态成员,即OuterClass.InnerClass.i因为中间步骤不是静态的。

回答by Saif

  1. class Initialization sequenceis a critical reason.
  1. class 初始化顺序是一个关键原因。

As inner classes are dependent on the instance of enclosing/Outer class, so Outer class need to be initialized before the initialization of the Inner class.
This is JLS says about class Initialization.The point we need is, class T will be initialize if

由于内部类依赖于封闭/外部类的实例,因此外部类需要在内部类初始化之前进行初始化。
这是 JLS 关于类初始化的说法。我们需要的一点是,类 T 将被初始化,如果

  • A static field declared by T is used and the field is not a constant variable.
  • 使用 T 声明的静态字段,该字段不是常量变量。

So if inner class have an static field accessing that will cause initializing the inner class, but that will not ensure that the enclosing class is initialized.

因此,如果内部类有一个静态字段访问,这将导致初始化内部类,但这并不能确保初始化封闭类。

  1. It would violate some basic rules. you can skip to the last section (to two cases) to avoid noob stuff

  1. 它会违反一些基本规则你可以跳到最后一节(到two cases)以避免菜鸟的东西

One thing about static nestedclass, when some nested classis staticit will behave just like a normal class in every way and it is associated with the Outer class.

关于 的一件事,当一些是时,它将在各方面表现得像一个普通类,并且它与外部类相关联。static nestedclassnested classstatic

But the concept of Inner class/ non-staticnested classis it will be associated with the instanceof outer/enclosing class. Please note associated with instancenot the class. Now associating with instance clearly means that (from the concept of instance variable) it will exist inside a instance and will be different among instances.

但是Inner class/的概念将与外部/封闭类相关联。请注意与实例相关而不是类。现在与实例关联清楚地意味着(从实例变量的概念)它将存在于一个实例中,并且在实例之间会有所不同。 non-staticnested classinstance

Now, when we make something static we expect it will be initialized when the class is being loaded and should be shared among all instances. But for being non-static, even inner classes themselves (you can definitely forget about instance of inner class for now) are not shared with all instance of the outer/enclosing class (at least conceptually), then how can we expect that some variable of inner class will be shared among all the instance of the inner class.

现在,当我们将某些东西设为静态时,我们期望它会在类加载时被初始化,并且应该在所有实例之间共享。但是由于是非静态的,即使内部类本身(您现在绝对可以忘记内部类的实例)也不会与外部/封闭类的所有实例共享(至少在概念上),那么我们怎么能期望某些变量内部类的所有实例将在内部类的所有实例之间共享。

So if Java allow us to use static variable inside not static nested class. there will be two cases.

因此,如果 Java 允许我们在非静态嵌套类中使用静态变量。会有两种情况

  • If it is shared with all the instance of inner class it will violate the concept of context of instance(instance variable). It's a NO then.
  • If it is not shared with all instance it will violate the the concept of being static. Again NO.
  • 如果它与内部类的所有实例共享,它将违反context of instance(实例变量)的概念。那就不行了。
  • 如果它不与所有实例共享,它将违反静态的概念。再次没有。

回答by Mannu

In simple words, non-static inner classes are instance variable for outer class, and they are created only when an outer class is created and an outer class object is created at run-time while static variables are created at class loading time. So non-static inner class is runtime thing that's why static not the part of a non-static inner class.

简单来说,非静态内部类是外部类的实例变量,只有在创建外部类并在运行时创建外部类对象时才会创建它们,而在类加载时创建静态变量。所以非静态内部类是运行时的东西,这就是为什么静态不是非静态内部类的一部分。

NOTE: treat inner classes always like a variable for an outer class they may be static or non-static like any other variables.

注意:将内部类始终视为外部类的变量,它们可以像任何其他变量一样是静态或非静态的。

回答by a.j. hrishikesh

Because it would cause ambiguity in the meaning of "static".

因为它会导致“静态”的含义产生歧义。

Inner classes cannot declare static members other than compile-time constants. There would be an ambiguity about the meaning of “static.” Does it mean there is only one instance in the virtual machine? Or only one instance per outer object? The language designers decided not to tackle this issue.

内部类不能声明编译时常量以外的静态成员。“静态”的含义会有歧义。这是否意味着虚拟机中只有一个实例?还是每个外部对象只有一个实例?语言设计者决定不解决这个问题。

Taken from "Core Java SE 9 for the Impatient" by Cay S. Horstmann. Pg 90 Chapter 2.6.3

摘自 Cay S. Horstmann 的“Core Java SE 9 for the Impatient”。第 90 页第 2.6.3 章