Java 为什么我们不能在(非静态)内部类中有静态方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/975134/
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-11 21:46:17  来源:igfitidea点击:

Why can't we have static method in a (non-static) inner class?

javaclassstaticinner-classes

提问by Rahul Garg

Why can't we have static method in a non-static inner class?

为什么我们不能在非静态内部类中有静态方法?

If I make the inner class static it works. Why?

如果我将内部类设为静态,它就可以工作。为什么?

采纳答案by Bill the Lizard

Because an instance of an inner class is implicitly associated with an instance of its outer class, it cannot define any static methods itself. Since a static nested class cannot refer directly to instance variables or methods defined in its enclosing class, it can use them only through an object reference, it's safe to declare static methods in a static nested class.

因为内部类的实例与其外部类的实例隐式关联,所以它本身不能定义任何静态方法。由于静态嵌套类不能直接引用其封闭类中定义的实例变量或方法,因此只能通过对象引用使用它们,因此在静态嵌套类中声明静态方法是安全的。

回答by B.E.

An inner class is something completely different from a static nested class although both are similar in syntax. Static nested classes are only a means for grouping whereas inner classes have a strong association - and access to all values of - their outer class. You should be sure why you want to use an inner class and then it should come pretty natural which one you have to use. If you need to declare a static method it's probably a static nested class you want anyway.

内部类与静态嵌套类完全不同,尽管两者在语法上相似。静态嵌套类只是分组的一种方式,而内部类具有很强的关联 - 并且可以访问它们的外部类的所有值。您应该确定为什么要使用内部类,然后应该很自然地知道您必须使用哪一个。如果您需要声明一个静态方法,它可能是您想要的静态嵌套类。

回答by mR_fr0g

You are allowed static methods on static nested classes. For example

您可以使用静态嵌套类的静态方法。例如

public class Outer {

  public static class Inner {

    public static void method() {

    }
  }
}

回答by gustafc

I have a theory, which may or may not be correct.

我有一个理论,可能正确也可能不正确。

First, you should know some things about how inner classes are implemented in Java. Suppose you've got this class:

首先,您应该了解 Java 内部类是如何实现的。假设你有这个类:

class Outer {
    private int foo = 0;
    class Inner implements Runnable {
        public void run(){ foo++; }
    }
    public Runnable newFooIncrementer(){ return new Inner(); }
}

When you compile it, the generated bytecode will look as if you wrote something like this:

当你编译它时,生成的字节码看起来就像你写了这样的东西:

class Outer {
    private int foo = 0;
    static class Inner implements Runnable {
        private final Outer this
class Outer {
    private int foo = 0;
    class Inner {
        public static void incrFoo(){ foo++; }
    }
}
; public Inner(Outer outer){ this
class Outer {
    private int foo = 0;
    static class Inner {
        private final Outer this
Outer.test();
; public Inner(Outer outer){ this
Outer.Inner.innerTest();
= outer; } public static void incrFoo(){ this
class Outer {
   int outID;

   class Inner {
      static int nextID;
      int id = nextID++;

      String getID() {
         return outID + ":" + id;
      }
   }
}
.foo++; } } }
= outer; } public void run(){ this
Outer -> Inner -> getID()
.foo++; } } public Runnable newFooIncrementer(){ return new Inner(this); } }

Now, if we did allow static methods in non-static inner classes, you might want to do something like this.

现在,如果我们确实允许在非静态内部类中使用静态方法,您可能想要做这样的事情。

Outer static -> Outer instance -> instanceMethod()
         \----> staticMethod()

... which looks fairly reasonable, as the Innerclass seems to have one incarnation per Outerinstance. But as we saw above, the non-static inner classes really are just syntactic sugar for static "inner" classes, so the last example would be approximately equivalent to:

...看起来相当合理,因为Inner该类似乎每个Outer实例都有一个化身。但是正如我们在上面看到的,非静态内部类实际上只是静态“内部”类的语法糖,因此最后一个示例大致相当于:

Outer static -> Outer instance -> Inner instance -> getID()
         \------ Inner static ------^

... which clearly won't work, since this$0is non-static. This sort of explains why static methods aren't allowed (although you could make the argument that you could allow static methods as long as they didn't reference the enclosing object), and why you can't have non-final static fields (it would be counter-intuitive if instances of non-static inner classes from different objects shared "static state"). It also explains why final fields areallowed (as long as they don't reference the enclosing object).

...这显然不起作用,因为this$0它是非静态的。这种解释了为什么不允许使用静态方法(尽管您可以提出这样的论点,即只要静态方法不引用封闭对象,您就可以允许它们),以及为什么不能有非最终静态字段(如果来自不同对象的非静态内部类的实例共享“静态状态”,那将是违反直觉的)。这也解释了为什么最终场允许的(只要他们不引用封闭的对象)。

回答by Eddie

There's not much point to allowing a static method in a non-static inner class; how would you access it? You cannot access (at least initially) a non-static inner class instance without going through an outer class instance. There is no purely static way to create a non-static inner class.

在非静态内部类中允许静态方法没有多大意义;你将如何访问它?您不能在不通过外部类实例的情况下访问(至少最初是)非静态内部类实例。没有纯粹的静态方法来创建非静态内部类。

For an outer class Outer, you can access a static method test()like this:

对于外部类Outer,您可以访问这样的静态方法test()

##代码##

For a static inner class Inner, you can access its static method innerTest()like this:

对于静态内部类Inner,您可以innerTest()像这样访问其静态方法:

##代码##

However, if Inneris not static, there is now no purely static way to reference the method innertest. Non-static inner classes are tied to a specific instance of their outer class. A function is different from a constant, in that a reference to Outer.Inner.CONSTANTis guaranteed to be unambiguous in a way that a function call Outer.Inner.staticFunction();is not. Let's say you have Inner.staticFunction()that calls getState(), which is defined in Outer. If you try to invoke that static function, you now have an ambiguous reference to the Inner class. That is, on which instance of the inner class do you invoke the static function? It matters. See, there is no truly static way to reference that static method, due to the implicit reference to the outer object.

但是,如果Inner不是静态的,那么现在没有纯粹静态的方式来引用方法innertest。非静态内部类与其外部类的特定实例相关联。函数与常量的不同之处Outer.Inner.CONSTANT在于,以函数调用Outer.Inner.staticFunction();所没有的方式保证对的引用是明确的。比方说,你有Inner.staticFunction()那个电话getState(),这是在定义Outer。如果您尝试调用该静态函数,您现在对 Inner 类的引用不明确。也就是说,在内部类的哪个实例上调用静态函数?这很重要。看,由于对外部对象的隐式引用,没有真正静态的方法来引用该静态方法。

Paul Bellora is correct that the language designers could have allowed this. They would then have to carefully disallow any access to the implicit reference to the outer class in static methods of the non-static inner class. At this point, what is the value to this being an inner class if you cannot reference the outer class, except statically? And if static access is fine, then why not declare the whole inner class static? If you simply make the inner class itself static, then you have no implicit reference to the outer class, and you no longer have this ambiguity.

Paul Bellora 是正确的,语言设计者可以允许这样做。然后,他们必须小心地禁止在非静态内部类的静态方法中对外部类的隐式引用进行任何访问。在这一点上,如果您不能引用外部类(静态除外),那么作为内部类的价值是什么?如果静态访问很好,那么为什么不将整个内部类声明为静态呢?如果你只是让内部类本身是静态的,那么你就没有对外部类的隐式引用,并且不再有这种歧义。

If you actually needstatic methods on a non-static inner class, then you probably need to rethink your design.

如果您确实需要在非静态内部类上使用静态方法,那么您可能需要重新考虑您的设计。

回答by Malay

suppose there are two instances of outer class & they both have instantiated inner class.Now if inner class has one static member then it will keep only one copy of that member in heap area.In this case both objects of outer class will refer to this single copy & they can alter it together.This can cause "Dirty read" situation hence to prevent this Java has applied this restriction.Another strong point to support this argument is that java allows final static members here, those whose values can't be changed from either of outer class object. Please do let me if i am wrong.

假设有两个外部类的实例,它们都实例化了内部类。现在如果内部类有一个静态成员,那么它将在堆区域中只保留该成员的一个副本。在这种情况下,外部类的两个对象都将引用 this单个副本&他们可以一起改变它。这可能导致“脏读”情况,因此为了防止这个Java应用了这个限制。支持这个论点的另一个优点是java允许在这里使用final静态成员,那些值不能为从任何一个外部类对象更改。如果我错了,请让我。

回答by Russell Zahniser

Short answer: The mental model most programmers have of how scope works is not the model used by javac. Matching the more intuitive model would have required a big change to how javac works.

简短回答:大多数程序员对作用域如何工作的心理模型不是 javac 使用的模型。匹配更直观的模型需要对 javac 的工作方式进行重大改变。

The main reason that static members in inner classes are desirable is for code cleanliness - a static member used only by an inner class ought to live inside it, rather than having to be placed in the outer class. Consider:

内部类中的静态成员是可取的主要原因是为了代码清洁 - 仅由内部类使用的静态成员应该位于内部类中,而不必放置在外部类中。考虑:

##代码##

Consider what is going on in getID() when I use the unqualified identifier "outID". The scope in which this identifier appears looks something like:

考虑当我使用非限定标识符“outID”时 getID() 中发生了什么。此标识符出现的范围类似于:

##代码##

Here, again because this is just how javac works, the "Outer" level of the scope includes both static and instance members of Outer. This is confusing because we are usually told to think of the static part of a class as another level of the scope:

在这里,再次因为这正是 javac 的工作方式,作用域的“外部”级别包括外部的静态成员和实例成员。这是令人困惑的,因为我们通常被告知将类的静态部分视为范围的另一个级别:

##代码##

In this way of thinking about it, of course staticMethod() can only see static members of Outer. But if that were how javac works, then referencing an instance variable in a static method would result in a "name cannot be resolved" error. What really happens is that the name is found in scope, but then an extra level of check kicks in and figures out that the name was declared in an instance context and is being referenced from a static context.

这样想来,当然staticMethod()只能看到Outer的静态成员。但是如果这就是 javac 的工作方式,那么在静态方法中引用实例变量将导致“名称无法解析”错误。真正发生的情况是名称是在作用域中找到的,但随后会进行额外级别的检查,并确定名称是在实例上下文中声明的,并且是从静态上下文中引用的。

OK, how does this relate to inner classes? Naively, we think there is no reason inner classes can't have a static scope, because we are picturing the scope working like this:

好的,这与内部类有什么关系?天真地,我们认为内部类没有理由不能有静态作用域,因为我们想象作用域是这样工作的:

##代码##

In other words, static declarations in the inner class and instance declarations in the outer class are both in scope within the instance context of the inner class, but neither of these is actually nested in the other; both are instead nested in the static scope of Outer.

换句话说,内部类中的静态声明和外部类中的实例声明都在内部类的实例上下文中的作用域内,但实际上两者都没有嵌套在另一个中;两者都嵌套在外部的静态范围内。

That's just not how javac works - there is a single level of scope for both static and instance members, and scope always strictly nests. Even inheritance is implemented by copying declarations into the subclass rather than branching and searching the superclass scope.

这不是 javac 的工作方式 - 静态成员和实例成员都有一个单一级别的范围,并且范围始终严格嵌套。甚至继承也是通过将声明复制到子类而不是分支和搜索超类范围来实现的。

To support static members of inner classes javac would have to either split static and instance scopes andsupport branching and rejoining scope hierarchies, or it would have to extend its simple boolean "static context" idea to change to track the type of context at all levels of nested class in the current scope.

为了支持内部类的静态成员,javac 必须要么拆分静态范围和实例范围,支持分支和重新加入范围层次结构,要么必须扩展其简单的布尔“静态上下文”思想来更改以跟踪所有级别的上下文类型当前作用域中的嵌套类。

回答by Don Li

The only reason is "not a must", so why bother to support it?

唯一的原因是“不是必须的”,那么为什么要支持它呢?

Syntactically,there is no reason to prohibit an inner class from having static members. Although an instance of Inneris associated with an instance of Outer, it's still possible to use Outer.Inner.myStaticto refer a static member of Innerif java decides to do so.

从语法上讲,没有理由禁止内部类具有静态成员。尽管 的实例Inner与 的实例相关联Outer,但如果 java 决定这样做,仍然可以使用Outer.Inner.myStatic来引用 的静态成员Inner

If you need to share something among all the instances of Inner, you can just put them into Outeras static members. This is not worse than you use static members in Inner, where Outercan still access any private member of Inneranyway(does not improve encapsulation).

如果您需要在 的所有实例之间共享某些内容Inner,您可以将它们Outer作为静态成员放入。这并不比你在 中使用静态成员更糟糕Inner,在那里Outer仍然可以访问任何私有成员Inner(不会改进封装)。

If you need to share something among all the instances of Innercreated by one outerobject,it makes more sense to put them into Outerclass as ordinary members.

如果您需要Inner在一个outer对象创建的所有实例之间共享某些内容,将它们Outer作为普通成员放入类更有意义。

I don't agree the opinion that "a static nested class is pretty much just a top level class". I think its better to really regard a static nested class/inner class as a part of the outer class, because they can access outer class's private members. And members of outer class are "members of inner class" as well. So there is no need to support static member in inner class. An ordinary/static member in outer class will suffice.

我不同意“静态嵌套类几乎只是顶级类”的观点。我认为最好将静态嵌套类/内部类真正视为外部类的一部分,因为它们可以访问外部类的私有成员。外部类的成员也是“内部类的成员”。所以不需要在内部类中支持静态成员。外部类中的普通/静态成员就足够了。

回答by Creative_Cimmons

It is useless to have inner class members as static because you won't be able to access them in the first place.

将内部类成员设为静态是没有用的,因为您一开始就无法访问它们。

Think about this, to access a static member you use className.memberName ,, in our case , it should be something like outerclassName.innerclassName.memberName,,, now do you see why innerclass must be static....

想想看,要访问静态成员,您可以使用 className.memberName ,在我们的例子中,它应该是类似 outerclassName.innerclassName.memberName 的东西,现在你明白为什么 innerclass 必须是静态的了....

回答by akhil_mittal

Why can't we have static method in a non-static inner class ?

为什么我们不能在非静态内部类中有静态方法?

Note:A non-static nested class is known as inner class so you do not have non-static inner classas such.

注意:非静态嵌套类称为内部类,因此您没有内部类non-static inner class

An inner class instance has no existence without a corresponding instance of outer class. An inner class cannot declare static members other than compile time constants. If it were allowed then there would have been ambiguity about meaning of static. In that case there would have been certain confusions:

没有相应的外部类实例,内部类实例就不存在。内部类不能声明编译时常量以外的静态成员。如果允许,那么 的含义就会产生歧义static。在这种情况下,会出现某些混淆:

  1. Does it mean there is only one instance in VM?
  2. Or only one instance per outer object?
  1. 这是否意味着 VM 中只有一个实例?
  2. 还是每个外部对象只有一个实例?

That is why the designers probably took the decision of not handling this issue at all.

这就是为什么设计师可能决定根本不处理这个问题。

If I make the inner class static it works. Why ?

如果我将内部类设为静态,它就可以工作。为什么 ?

Again you cannot make an inner class static rather you can declare a static class as nested. In that case this nested class is actually part of outer class and can have static members without any issue.

同样,您不能将内部类设为静态,而可以将静态类声明为嵌套类。在这种情况下,这个嵌套类实际上是外部类的一部分,并且可以拥有静态成员而不会出现任何问题。