What are final inner classes? - java

What does it means to declare a non-static inner class as final?
I have tried many links on google and stackoverflow.com as well but all of them seem to be dealing about inner classes accessing final members not final inner classes itself.
I found this link on google but even it doesn't explains it.
Thanx in advance!

There is no semantic difference between making a top-level class final and making an inner class final: it tells the compiler that you cannot inherit from the class. Marking classes final is sometimes done to let the compiler skip a virtual table lookup, but this is often regarded as premature micro-optimization.

It has the same semantics as an outer class being declared final: the class cannot be extended.
Consider this example:
public class MyClass {
public class A {
}
public class B extends A {
}
}
If you add the final modifier to A it will generate a compilation error.

Well, inner classes are not any way different from outer classes in that context. So the following code is perfectly valid.
class Outer {
int some_member;
class Inner {
void method();
}
}
class OuterExtendsInner extends Outer.Inner{
}
As we all know, the purpose of declaring a class final is that we prevent any outside intruder from subclassing the class and exploit its facilities, the same way we can do in case of inner classes.

Related

Why private members of nested class are accessible in outer class [duplicate]

I observed that Outer classes can access inner classes private instance variables. How is this possible? Here is a sample code demonstrating the same:
class ABC{
class XYZ{
private int x=10;
}
public static void main(String... args){
ABC.XYZ xx = new ABC().new XYZ();
System.out.println("Hello :: "+xx.x); ///Why is this allowed??
}
}
Why is this behavior allowed?
The inner class is just a way to cleanly separate some functionality that really belongs to the original outer class. They are intended to be used when you have 2 requirements:
Some piece of functionality in your outer class would be most clear if it was implemented in a separate class.
Even though it's in a separate class, the functionality is very closely tied to way that the outer class works.
Given these requirements, inner classes have full access to their outer class. Since they're basically a member of the outer class, it makes sense that they have access to methods and attributes of the outer class -- including privates.
If you like to hide the private members of your inner class, you may define an Interface with the public members and create an anonymous inner class that implements this interface. Example bellow:
class ABC{
private interface MyInterface{
void printInt();
}
private static MyInterface mMember = new MyInterface(){
private int x=10;
public void printInt(){
System.out.println(String.valueOf(x));
}
};
public static void main(String... args){
System.out.println("Hello :: "+mMember.x); ///not allowed
mMember.printInt(); // allowed
}
}
The inner class is (for purposes of access control) considered to be part of the containing class. This means full access to all privates.
The way this is implemented is using synthetic package-protected methods: The inner class will be compiled to a separate class in the same package (ABC$XYZ). The JVM does not support this level of isolation directly, so that at the bytecode-level ABC$XYZ will have package-protected methods that the outer class uses to get to the private methods/fields.
There's a correct answer appearing on another question similar to this:
Why can the private member of an nested class be accessed by the methods of the enclosing class?
It says there's a definition of private scoping on JLS - Determining Accessibility:
Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
Thilo added a good answer for your first question "How is this possible?". I wish to elaborate a bit on the second asked question: Why is this behavior allowed?
For starters, let's just be perfectly clear that this behavior is not limited to inner classes, which by definition are non-static nested types. This behavior is allowed for all nested types, including nested enums and interfaces which must be static and cannot have an enclosing instance. Basically, the model is a simplification down to the following statement: Nested code have full access to enclosing code - and vice versa.
So, why then? I think an example illustrate the point better.
Think of your body and your brain. If you inject heroin into your arm, your brain gets high. If the amygdala region of your brain see what he believe is a threat to your personally safety, say a wasp for example, he'll make your body turn the other way around and run for the hills without You "thinking" twice about it.
So, the brain is an intrinsic part of the body - and strangely enough, the other way around too. Using access control between such closely related entities forfeit their claim of relationship. If you do need access control, then you need to separate the classes more into truly distinct units. Until then, they are the same unit. A driving example for further studies would be to look at how a Java Iterator usually is implemented.
Unlimited access from enclosing code to nested code makes it, for the most part, rather useless to add access modifiers to fields and methods of a nested type. Doing so is adding clutter and might provide a false sense of safety for new comers of the Java programming language.
An IMHO important use case for inner classes is the factory pattern.
The enclosing class may prepare an instance of the inner class w/o access restrictions and pass the instance to the outside world, where private access will be honored.
In contradiction to abyx declaring the class static doesn't change access restrictions to the enclosing class, as shown below. Also the access restrictions between static classes in the same enclosing class are working. I was surprised ...
class MyPrivates {
static class Inner1 { private int test1 = 2; }
static class Inner2 { private int test2 = new Inner1().test1; }
public static void main(String[] args) {
System.out.println("Inner : "+new Inner2().test2);
}
}
Access restrictions are done on a per class basis. There is no way for a method declared in a class to not be able to access all of the instance/class members. It this stands to reason that inner classes also have unfettered access to the members of the outer class, and the outer class has unfettered access to the members of the inner class.
By putting a class inside another class you are making it tightly tied to the implementation, and anything that is part of the implementation should have access to the other parts.
The logic behind inner classes is that if you create an inner class in an outer class, that's because they will need to share a few things, and thus it makes sense for them to be able to have more flexibility than "regular" classes have.
If, in your case, it makes no sense for the classes to be able to see each other's inner workings - which basically means that the inner class could simply have been made a regular class, you can declare the inner class as static class XYZ. Using static will mean they will not share state (and, for example new ABC().new XYZ() won't work, and you will need to use new ABC.XYZ().
But, if that's the case, you should think about whether XYZ should really be an inner class and that maybe it deserves its own file. Sometimes it makes sense to create a static inner class (for example, if you need a small class that implements an interface your outer class is using, and that won't be helpful anywhere else). But at about half of the time it should have been made an outer class.
Inner class is regarded as an attribute of the Outer class. Therefore, no matter the Inner class instance variable is private or not, Outer class can access without any problem just like accessing its other private attributes(variables).
class Outer{
private int a;
class Inner{
private int b=0;
}
void outMethod(){
a = new Inner().b;
}
}
Because your main() method is in the ABC class, which can access its own inner class.

static class in java

How do I declare a static class in java? eclipse wants me to remove "static" from the declaration.
static public class Constants {
First to answer your question:
Only a Nested class can be declared static. A top level class cannot declared be static.
Secondly, Inner class is a nested class that is not explicitly declared static. See the java language spec. So contrary to some answers here, Inner classes cannot be static
To quote an example from the spec:
class HasStatic{
static int j = 100;
}
class Outer{
class Inner extends HasStatic{
static final int x = 3; // ok - compile-time constant
static int y = 4; // compile-time error, an inner class
}
static class NestedButNotInner{
static int z = 5; // ok, not an inner class
}
interface NeverInner{} // interfaces are never inner
}
If by 'static' you mean 'can have only static members', there's no such thing in Java.
Inner classes (and only them) can be static, but that's a different concept. Inner static classes can still have instance members.
Eclipse complains correctly, your code won't compile as Top level class can't be declared as static.
You need to first understand what static class means.
static class :
Top level class can't be declared as static. Only Member and Nested top-level classes can be defined as static.
You declare member classes when you want to use variables and methods of the containing class without explicit delegation. When you declare a member class, you can instantiate that member class only within the context of an object of the outer class in which this member class is declared. If you want to remove this restriction, you declare the member class a static class.When you declare a member class with a static modifier, it becomes a nested top-level class and can be used as a normal top-level class as explained above.
nested top-level class is a member classes with a static modifier. A nested top-level class is just like any other top-level class except that it is declared within another class or interface. Nested top-level classes are typically used as a convenient way to group related classes without creating a new package.
Also check when should we go for static class,variables and methods in java
As you have already been told from the other comments, classes cannot be declared static. However there are alternatives to this problem.
The most simple one is to precede all member variables and methods with the static modifier. This essentially does what you want.
A slightly more involved alternative is to make the class a singleton. This is a class in which through the use of a private constructor, and an instanceOf() method, or just an Enum, you can only have one instance of that class. Semantically and syntactically you treat that instance as an ordinary instance of whatever particular class you are making a singleton, but you can only have a single instance of that class, which you retrieve via SomeObject.instanceOf(), or in an Enum implementation, SomeObject.INSTANCE.
You would normally use Enums to implement this, minus the edge cases where you are extending another class.
For more complete information on singletons visit the link below.
Design Patterns in Java - Singleton
There is no direct equivalent of C# static classes in Java, but the closest thing in my opinion is an empty enum, which might seem weird at first, but makes sense the more you think about it. An enum in Java (unlike in C#) is essentially a set of singleton instances that all implement the same abstract base class and interfaces. The quickest and safest way to make a normal singleton in Java is like so:
enum Foo {
INSTANCE;
public Bar doSomething(Baz baz) {
return Bar.fromBaz(baz); // yadda yadda
}
}
So since we are dealing with sets of singletons, it make sense that we can have an empty set. And an empty set means there can be no instances. This is conceptually the same as a static class in C#.
enum MyUtilities {
;
static Bar doSomething(Baz baz) {
return Bar.fromBaz(baz); // yadda yadda
}
static final String SOME_CONSTANT = "QUX";
}
This is great because you won't lose test coverage because of hard to test private constructors in a final class, and the code is cleaner than a final class with an empty private constructor.
Now, if the static classes are meant to all work on a single Interface and you have control of that Interface, then you should implement the static methods on that Interface itself (something you can't do in C#).
All top level classes are implicitly static, meaning they can be accessed by everybody. So it makes sense only to make inner classes optionally static.

Using extends in Java gives enclosing instance error

I'm trying to use extends (inheritance) in Java. I made a quick abstract class to extend from, and then extended it. However my IDE now is saying that "An enclosing instance that contains abstract_class is required" and gives my constructor for the derived classes big error lines. What on earth is it going on about? The abstract class doesn't have or need any sort of constructor.
Just for reference, I'm using extends rather than implements in part because the implementation details that I don't want to have to maintain for every derived class which are identical involve using reflection on this.
Edit: I've read some of the responses. What in God's name is a static (or non-static, for that matter) class? And just to irritate all of you, it didn't solve the problem.
// some_class.java
public class some_class {
public static abstract class abstract_class {
...
}
...
}
// Model.java
public class Model extends some_class.abstract_class {
public Model(...) {
// No enclosing instance! Critical error.
...
}
...
}
And I thought that C++'s header files were bad.
The code you posted seems to compile just fine for me. Try doing a clean build in your IDE and it should work.
Just for your own curiosity, Java has 2 types of inner classes: static and regular or (non-static). If you don't include the static keyword for an inner class definition, it means that an instance of that class will always require an instance of the parent class. For ex:
public class MyClassOuter {
//...
public class MyClassInner {
//..
}
}
If you write that, it is understood that any instance of MyClassInner will have an implicit reference to an instance of MyClassOuter.
Static, on the other, hand implies no such thing. It is just a class definition that happens to be inside another class definition. The outer class is used almost like a package (though not quite).
if you have
interface MyInterface
{
abstract class MyAbstractClass {
// ...
}
}
and then you try
class ConcreteClass extends MyAbstractClass {
}
You will get the error described. The fix is to either move MyAbstractClass to a top-level class (put it in it's own file - not strictly necessary for non-public classes, but keeps the code organized.) Alternatively, add the static modifier to the MyAbstractClass declaration.
The "enclosing instance" message almost certainly implies that you have a (non-static) inner class for your superclass. In most cases, inner classes can and should be static - that's likely the best workaround here. Alternatively, as the message says, you will need to use an enclosing instance of the "outer" class, if your parent really makes sense as a non-static inner class.
Posting some code will help disambiguate between these causes and suggest the best way to resolve it. I'll also be able to give examples of the resolutions with the right class names - currently I don't think arbitrary names will help that much as it sounds like you hadn't identified the inner/outer class issue.
You need to in your child class add in the constructor super() that super class can be created.
class A{
.
.
.
class B{
. . .
}
}
if you want to access the Class B and it it is not static inner class you can write the code as
A.B objOfB = new A(). new B();

Why can outer Java classes access inner class private members?

I observed that Outer classes can access inner classes private instance variables. How is this possible? Here is a sample code demonstrating the same:
class ABC{
class XYZ{
private int x=10;
}
public static void main(String... args){
ABC.XYZ xx = new ABC().new XYZ();
System.out.println("Hello :: "+xx.x); ///Why is this allowed??
}
}
Why is this behavior allowed?
The inner class is just a way to cleanly separate some functionality that really belongs to the original outer class. They are intended to be used when you have 2 requirements:
Some piece of functionality in your outer class would be most clear if it was implemented in a separate class.
Even though it's in a separate class, the functionality is very closely tied to way that the outer class works.
Given these requirements, inner classes have full access to their outer class. Since they're basically a member of the outer class, it makes sense that they have access to methods and attributes of the outer class -- including privates.
If you like to hide the private members of your inner class, you may define an Interface with the public members and create an anonymous inner class that implements this interface. Example bellow:
class ABC{
private interface MyInterface{
void printInt();
}
private static MyInterface mMember = new MyInterface(){
private int x=10;
public void printInt(){
System.out.println(String.valueOf(x));
}
};
public static void main(String... args){
System.out.println("Hello :: "+mMember.x); ///not allowed
mMember.printInt(); // allowed
}
}
The inner class is (for purposes of access control) considered to be part of the containing class. This means full access to all privates.
The way this is implemented is using synthetic package-protected methods: The inner class will be compiled to a separate class in the same package (ABC$XYZ). The JVM does not support this level of isolation directly, so that at the bytecode-level ABC$XYZ will have package-protected methods that the outer class uses to get to the private methods/fields.
There's a correct answer appearing on another question similar to this:
Why can the private member of an nested class be accessed by the methods of the enclosing class?
It says there's a definition of private scoping on JLS - Determining Accessibility:
Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
Thilo added a good answer for your first question "How is this possible?". I wish to elaborate a bit on the second asked question: Why is this behavior allowed?
For starters, let's just be perfectly clear that this behavior is not limited to inner classes, which by definition are non-static nested types. This behavior is allowed for all nested types, including nested enums and interfaces which must be static and cannot have an enclosing instance. Basically, the model is a simplification down to the following statement: Nested code have full access to enclosing code - and vice versa.
So, why then? I think an example illustrate the point better.
Think of your body and your brain. If you inject heroin into your arm, your brain gets high. If the amygdala region of your brain see what he believe is a threat to your personally safety, say a wasp for example, he'll make your body turn the other way around and run for the hills without You "thinking" twice about it.
So, the brain is an intrinsic part of the body - and strangely enough, the other way around too. Using access control between such closely related entities forfeit their claim of relationship. If you do need access control, then you need to separate the classes more into truly distinct units. Until then, they are the same unit. A driving example for further studies would be to look at how a Java Iterator usually is implemented.
Unlimited access from enclosing code to nested code makes it, for the most part, rather useless to add access modifiers to fields and methods of a nested type. Doing so is adding clutter and might provide a false sense of safety for new comers of the Java programming language.
An IMHO important use case for inner classes is the factory pattern.
The enclosing class may prepare an instance of the inner class w/o access restrictions and pass the instance to the outside world, where private access will be honored.
In contradiction to abyx declaring the class static doesn't change access restrictions to the enclosing class, as shown below. Also the access restrictions between static classes in the same enclosing class are working. I was surprised ...
class MyPrivates {
static class Inner1 { private int test1 = 2; }
static class Inner2 { private int test2 = new Inner1().test1; }
public static void main(String[] args) {
System.out.println("Inner : "+new Inner2().test2);
}
}
Access restrictions are done on a per class basis. There is no way for a method declared in a class to not be able to access all of the instance/class members. It this stands to reason that inner classes also have unfettered access to the members of the outer class, and the outer class has unfettered access to the members of the inner class.
By putting a class inside another class you are making it tightly tied to the implementation, and anything that is part of the implementation should have access to the other parts.
The logic behind inner classes is that if you create an inner class in an outer class, that's because they will need to share a few things, and thus it makes sense for them to be able to have more flexibility than "regular" classes have.
If, in your case, it makes no sense for the classes to be able to see each other's inner workings - which basically means that the inner class could simply have been made a regular class, you can declare the inner class as static class XYZ. Using static will mean they will not share state (and, for example new ABC().new XYZ() won't work, and you will need to use new ABC.XYZ().
But, if that's the case, you should think about whether XYZ should really be an inner class and that maybe it deserves its own file. Sometimes it makes sense to create a static inner class (for example, if you need a small class that implements an interface your outer class is using, and that won't be helpful anywhere else). But at about half of the time it should have been made an outer class.
Inner class is regarded as an attribute of the Outer class. Therefore, no matter the Inner class instance variable is private or not, Outer class can access without any problem just like accessing its other private attributes(variables).
class Outer{
private int a;
class Inner{
private int b=0;
}
void outMethod(){
a = new Inner().b;
}
}
Because your main() method is in the ABC class, which can access its own inner class.

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

Why can't we have static method in a non-static inner class?
public class Foo {
class Bar {
static void method() {} // Compiler error
}
}
If I make the inner class static it works. Why?
public class Foo {
static class Bar { // now static
static void method() {}
}
}
In Java 16+, both of these are valid.
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.
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:
Outer.Inner.innerTest();
However, if Inner is 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.CONSTANT is 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.
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.
If you actually need static methods on a non-static inner class, then you probably need to rethink your design.
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:
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$0;
public Inner(Outer outer){
this$0 = outer;
}
public void run(){ this$0.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.
class Outer {
private int foo = 0;
class Inner {
public static void incrFoo(){ foo++; }
}
}
... which looks fairly reasonable, as the Inner class seems to have one incarnation per Outer instance. 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:
class Outer {
private int foo = 0;
static class Inner {
private final Outer this$0;
public Inner(Outer outer){
this$0 = outer;
}
public static void incrFoo(){ this$0.foo++; }
}
}
... which clearly won't work, since this$0 is 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 are allowed (as long as they don't reference the enclosing object).
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 Inner is associated with an instance of Outer, it's still possible to use Outer.Inner.myStatic to refer a static member of Inner if java decides to do so.
If you need to share something among all the instances of Inner, you can just put them into Outer as static members. This is not worse than you use static members in Inner, where Outer can still access any private member of Inner anyway(does not improve encapsulation).
If you need to share something among all the instances of Inner created by one outer object,it makes more sense to put them into Outer class as ordinary members.
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.
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.
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.
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:
Does it mean there is only one instance in VM?
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.
This topic has garnered attention from many, still I will try to explain in the most simplest of terms.
Firstly, with reference to http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.1, a class or interface is initialized immediately before the first occurence/invocation of any member which is preceeded by the static keyword.
So, if we put up with a static member within an inner class, it will lead to the initialization of the inner class, not necessarily the outer/enclosing class. So, we hamper the class initialization sequence.
Also consider the fact that a non-static inner class is associated with the instance of an enclosing/outer class. So, associating with an instance will mean, that the inner class will exist inside an Outer class instance and will be different amongst instances.
Simplifying the point, in order to access the static member we need an instance of an Outer class, from which we will again need to create an instance of non-static inner class. Static members are not supposed to be bound to instances and therefore you receive a compilation error.
The work to add records to JDK16 also mentions that static methods and fields can now be used with inner classes, even permitting main() to launch the class.
For example this compiles and runs in JDK16, and can select either main() to be run as java Outer or java Outer$Inner:
public class Outer {
public static void main(String[] args) {
System.out.println("Outer class main xxx="+Inner.xxx+" nnn="+(++Inner.nnn)+" iii="+(--iii));
aaa();
Inner.zzz();
}
public static void aaa() {
System.out.println("aaa() nnn="+(++Inner.nnn)+" iii="+(--iii));
}
public static int iii = 100;
class Inner {
public static final String xxx= "yyy";
public static int nnn = 0;
public static void zzz() {
System.out.println("zzz() "+" nnn="+(++nnn)+" iii="+(--iii));
}
public static void main(String[] args) {
System.out.println("Inner class main xxx="+xxx+" nnn="+(++nnn)+" iii="+(--iii));
zzz();
aaa();
}
}
}
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.
First of all why someone want to define the static member in a non-static inner class? answer is, so that the outer class member can use those static member with the inner class name only, Right?
But for this case we can directly define the member in outer class. which will be associated with all object of inner class, within the outer class instance.
like below code,
public class Outer {
class Inner {
public static void method() {
}
}
}
can be written like this
public class Outer {
void method() {
}
class Inner {
}
}
So in my opinion not to complicate the code java designer is not allowing this functionality or we may see this functionality in future releases with some more features.
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.
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
You are allowed static methods on static nested classes. For example
public class Outer {
public static class Inner {
public static void method() {
}
}
}
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....

Categories

Resources