Why can't we have static method in a (non-stat

2019-01-02 14:36发布

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

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

14条回答
深知你不懂我心
2楼-- · 2019-01-02 14:59

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.

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:

class Outer {
   int outID;

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

      String getID() {
         return outID + ":" + id;
      }
   }
}

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

Outer -> Inner -> 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:

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

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.

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:

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

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.

To support static members of inner classes javac would have to either split static and instance scopes and support 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.

查看更多
不流泪的眼
3楼-- · 2019-01-02 15:03

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 class as such.

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:

  1. Does it mean there is only one instance in VM?
  2. Or only one instance per outer object?

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.

查看更多
还给你的自由
4楼-- · 2019-01-02 15:05

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....

查看更多
大哥的爱人
5楼-- · 2019-01-02 15:08

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.

查看更多
无色无味的生活
6楼-- · 2019-01-02 15:09

Try to treat the class as a normal field, then you will understand.

//something must be static. Suppose something is an inner class, then it has static keyword which means it's a static class
Outer.something 
查看更多
长期被迫恋爱
7楼-- · 2019-01-02 15:13

From: https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html

As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to that object's methods and fields. Also, because an inner class is associated with an instance, it cannot define any static members itself.

Oracle's explanation is superficial and handwavy. Since there's no technical or syntactic reason to preempt static members within an inner class (it's allowed in other languages such as C#) the Java designers' motivation was likely conceptual taste and/or a matter of technical convenience.

Here's my speculation:

Unlike top-level classes, inner classes are instance-dependent: an inner-class instance is associated with an instance of every one of its outer classes and has direct access to their members. This is the chief motivation for having them in Java. Expressed another way: an inner class is meant for instantiation in the context of an outer class instance. Without an outer class instance, an inner class ought not be any more usable than the other instance members of the outer class. Let's refer to this as the instance-dependent spirit of inner classes.

The very nature of static members (which are NOT object-oriented) clashes with the instance-dependent spirit of inner classes (which IS object-oriented) because you can reference/call a static member of an inner class without an outer class instance by using the qualified inner class name.

Static variables in particular may offend in yet another way: two instances of an inner class that are associated with different instances of the outer class would share static variables. Since variables are a component of state, the two inner class instances would, in effect, share state independently of the outer class instances they're associated with. It’s not that it’s unacceptable that static variables work this way (we accept them in Java as a sensible compromise to OOP purity), but there’s arguably a deeper offense to be had by allowing them in inner classes whose instances are already coupled with outer class instances by design. Forbidding static members within inner classes in favor of the instance-dependent spirit reaps the added bonus of preempting this deeper OOP offense.

On the other hand, no such offense is entailed by static constants, which do not meaningfully constitute state and so these are allowable. Why not forbid static constants for maximum consistency with the instance-dependent spirit? Perhaps because constants need not take up more memory than necessary (if they're forced to be non-static then they’re copied into every inner class instance which is potentially wasteful). Otherwise I can’t imagine the reason for the exception.

It may not be rock-solid reasoning but IMO it makes the most sense of Oracle's cursory remark on the matter.

查看更多
登录 后发表回答