In Java, nested classes can be either static or not. If they are static, they do not contain a reference to the pointer of the containing instance (they are also not called inner classes anymore, they are called nested classes).
Forgetting to make an nested class static when it does not need that reference can lead to problems with garbage collection or escape analysis.
Is it possible to make an anonymous inner class static as well? Or does the compiler figure this out automatically (which it could, because there cannot be any subclasses)?
For example, if I make an anonymous comparator, I almost never need the reference to the outside:
Collections.sort(list, new Comparator<String>(){
int compare(String a, String b){
return a.toUpperCase().compareTo(b.toUpperCase());
}
}
No, you can't, and no, the compiler can't figure it out. This is why FindBugs always suggests changing anonymous inner classes to named static nested classes if they don't use their implicit this reference.
Edit: Tom Hawtin - tackline says that if the anonymous class is created in a static context (e.g. in the main method), the anonymous class is in fact static. But the JLS disagrees:
An anonymous class is never abstract (§8.1.1.1). An anonymous class is always an inner class (§8.1.3); it is never static (§8.1.1, §8.5.1). An anonymous class is always implicitly final (§8.1.1.2).
Roedy Green's Java Glossary says that the fact that anonymous classes are allowed in a static context is implementation-dependent:
If you want to baffle those maintaining your code, wags have discovered javac.exe will permit anonymous classes inside static init code and static methods, even though the language spec says than anonymous classes are never static. These anonymous classes, of course, have no access to the instance fields of the object. I don’t recommend doing this. The feature could be pulled at any time.
Edit 2: The JLS actually covers static contexts more explicitly in §15.9.2:
Let C be the class being instantiated, and let i be the instance being created. If C is an inner class then i may have an immediately enclosing instance. The immediately enclosing instance of i (§8.1.3) is determined as follows.
If C is an anonymous class, then:
If the class instance creation expression occurs in a static context (§8.1.3), then i has no immediately enclosing instance.
Otherwise, the immediately enclosing instance of i is this.
So an anonymous class in a static context is roughly equivalent to a static nested class in that it does not keep a reference to the enclosing class, even though it's technically not a static class.
I think there's a bit of confusion in the nomenclature here, which admittedly is too silly and confusing.
Whatever you call them, these patterns (and a few variations with different visibility) are all possible, normal, legal Java:
public class MyClass {
class MyClassInside {
}
}
public class MyClass {
public static class MyClassInside {
}
}
public class MyClass {
public void method() {
JComponent jc = new JComponent() {
...
}
}
}
public class MyClass {
public static void myStaticMethod() {
JComponent jc = new JComponent() {
...
}
}
}
They are catered for in the language spec (if you're really bothered, see section 15.9.5.1 for the one inside the static method).
But this quote is just plain wrong:
javac.exe will permit anonymous
classes inside static init code and
static methods, even though the
language spec says than anonymous
classes are never static
I think the quoted author is confusing the static keyword with static context. (Admittedly, the JLS is also a bit confusing in this respect.)
Honestly, all of the patterns above are fine (whatever you call them "nested", "inner", "anonymous" whatever...). Really, nobody is going to suddenly remove this functionality in the next release of Java. Honestly!
Kind of. An anonymous inner class created in a static method will obviously be effectively static because there is no source for an outer this.
There are some technical differences between inner classes in static contexts and static nested classes. If you're interested, read the JLS 3rd Ed.
Inner classes can't be static - a static nested class is not an inner class. The Java tutorial talks about it here.
anonymous inner classes are never static (they can't declare static methods or non final static fields),but if they're defined in a static context (static method or static field) they behave as static in the sense that they can't access non-static (i.e. instance) members of the enclosing class (like everything else from a static context)
On the note of making an anonymous inner class static by calling them within a static method.
This doesn't actually remove the reference. You can test this by trying to serialize the anonymous class and not making the enclosing class serializable.
Related
I'm a bit confused with the explanation of the reason, due to which inner classes are not able to contain static fields or methods. I read, that "inner class is strongly associated with outer class, and when we declare static field/method inside of inner class, this requirement isn't fulfilled"
But what's behind it? Can someone explain it in more details?
You can figure it out from doc
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.
An instance of InnerClass can exist only within an instance of OuterClass and has direct access to the methods and fields of its enclosing instance. Here you are why you cannot declared static fields inside inner class
Edit: similar question may help you
Behind the scenes, inner classes have an implicit reference to the outer class. You can access it as OuterClassName.this. The compiler takes care of the work behind the scenes for you, but it is essentially the same as if you declared a field in the inner class with the type of outer class. It's just syntactic sugar saving you two lines of code.
The relevant part is, that an inner class cannot exist without an outer class. This was purely a design choice, made intentionally by designers of Java.
On the other hand, if the inner class is declared as static, the compiler will not generate and enforce an instance of outer class. In this case, outer class acts very much like a package - it is just a placeholder. In this case, inner class can have static fields too, so the limitation does not apply.
It was an unnecessary restriction that you could not use static declarations inside inner classes, but support for static methods and fields inside inner classes has been added and supported with the work to add records in JDK16.
This class won't compile and run unless JDK16 or higher is used:
public class Launch {
public static void main(String[] args) {
System.out.println("Launch main says Y.xxx="+Y.xxx);
aaa();
Y.zzz();
}
public static void aaa() {
System.out.println("aaa()");
}
class Y {
public static final String xxx= "yyY";
public static void zzz() {
System.out.println("zzz()");
}
public static void main(String[] args) {
System.out.println("Inner class Y main says xxx="+xxx);
zzz();
aaa();
}
}
}
After compilation the above the inner class main() can be launched using class name Launch$Y independently of the main for the outer class. For example:
java Launch$Y
=> prints:
Inner class Y main says xxx=yyY
zzz()
aaa()
java Launch
=> prints:
Launch main says Y.xxx=yyY
aaa()
zzz()
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 why does Java prohibit static fields/methods in inner classes?
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.
what I want to know is why java forbids static fields/methods inside inner classes
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 static features, for static is meant to work without an instance in the first place.
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?
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 counter class attribute, there is no way to share that value across two different instances.
class Employee {
public String name;
class InnerData {
static count; // ??? count of which ? a or b?
}
}
When you create the instance a and b in 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 InnerData class depends completely on each of the enclosing objects.
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.
I think this sounds reiterative but if you think about the differences between instance vs. class attributes, it will make sense.
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).
InnerClass cannot have static members because it belongs to an instance (of OuterClass). If you declare InnerClass as static to detach it from the instance, your code will compile.
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. static in this context allows that to happen without an enclosing instance of OuterClass.
From Java 16 onwards, this is no longer the case. Quoting from JEP 395 (on finalizing records):
Relax the longstanding restriction whereby an inner class cannot declare a member that is explicitly or implicitly static. This will become legal and, in particular, will allow an inner class to declare a member that is a record class.
Indeed, the following code can be compiled with Java 16 (tried with 16.ea.27):
public class NestingClasses {
public class NestedClass {
static final String CONSTANT = new String(
"DOES NOT COMPILE WITH JAVA <16");
static String constant() {
return CONSTANT;
}
}
}
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
}
}
}
class Initialization sequence is a critical reason.
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
A static field declared by T is used and the field is not a constant variable.
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.
It would violate some basic rules. you can skip to the last section (to two cases) to avoid noob stuff
One thing about static nested class, when some nested class is static it will behave just like a normal class in every way and it is associated with the Outer class.
But the concept of Inner class/ non-static nested class is it will be associated with the instance of outer/enclosing class. Please note associated with instance not 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.
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.
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.
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 need static 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++;
}
}
}
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.
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
In the Java language designers' own words:
Since nested classes were first introduced to Java, nested class
declarations that are inner have been prohibited from declaring static
members... It simplifies the language's task of resolving and
validating references to in-scope variables, methods, etc.
There was never any particularly grand conceptual or philosophical reason to prohibit this.
Simplifying things for the language was deemed an insufficient reason to continue to maintain this restriction. Along with the introduction of records in Java 16, they made the decision to relax the restriction.
Class Inner will be initialize if a static field declared by Inner is used and the field is not a constant variable.
class Outer{
class Inner{
static Inner obj = new Inner();
}
public static void main(String[] args){
Inner i = Inner.obj; // It woulds violate the basic rule: without existing Outer class Object there is no chance of existing Inner class Object.
}
}
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.i because the middle step is not static.
I have a couple of questions relating to nested classes within Java.
How do nested classes appear "under the hood", with regards to memory allocations?
You cannot declare a static variable within a nested class (I think the exact error was that static attributes can only be declared at the top level class). Why is this and what other restrictions are there for nested classes?
If possible, please say whether your answer is Java-specific, or whether C++ also follows the same rules?
Inner classes are exactly the same as regular classes as far as memory and compilation are concerned. (Perhaps there is some difference in the way they're managed in memory, but it's not visible to the average Java developer) In fact, when you compile a class that has an inner class, you can see the compiled .class file as OuterClass$InnerClass.class. So as far as I know, the JVM treats them the same.
As far as static variables are concerned, I'm not certain what the issue is. For example, this runs for me:
public class Tester {
public static void main(String[] args) {
System.out.println(InnerTester.MY_STRING);
}
public class InnerTester {
public static final String MY_STRING = "MY_STRING";
}
}
EDIT
As Jeffery pointed out, this does NOT compile:
public class Tester {
public static void main(String[] args) {
System.out.println(InnerTester.MY_STRING);
}
public class InnerTester {
public static String MY_STRING = "MY_STRING";
}
}
The difference is, I had the first static variable listed as final.
After thinking about this awhile, I agree with #Eugene. They allow static fields on inner classes to be final because then there's no problem with initialization. The value cannot change, you just initialize it to its value. If, however, the static field is not final, you then require an instance of the outer class to be created in order to initialize the field, and static members can't be tied to particular instances.
I found this discussion on it as well.
Basically a nested class is just a class with a field referencing the enclosing instance.
Unless it's a static nested class (inside which you can declare static fields/methods).
In this case it's just a class with another path element in the name (package + enclosing class name).
In other words. Non-static nested class (inner class) - cannot exists without enclosing instance (e.g. page inside a book). And you instantiate as follows:
Book book = ... // a book instance;
Book.Page page = book.new Page(); // requires an enclosing instance
But the static nested class - is completely independent, it's like just a question of name space. You can instantiate it as:
Outer.NestedStatic instance = new Outer.NestedStatic(); // just name-space
More information here: http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
A nested class is simply the definition of a type inside another class. Java does not care in what scope a new type is defined, and you do not need to "handle" this inner class in any special way.
It wouldn't make sense to have a non-static inner class with static fields, since any reference to a non-static inner class is necessarily an instance variable. Only if the inner class is made static would it even be possible to statically assign it -- in this case, the static inner class is a standalone class, with the enclosing class name acting as yet another namespace level.
For collection of smaller helper utility classes, I have created a general class MyUtils:
// MyUtils.java
public final class MyUtils
{
public static class Helper1 {};
public static class Helper2 {};
//...
}
This helper classes from inside MyUtils will be used in the other files of the package:
// MyClass1.java
public class MyClass1
{
private MyUtils.Helper1 help1 = new MyUtils.Helper1();
public void method ()
{
private MyUtils.Helper2 help2 = new MyUtils.Helper2();
}
}
To let them accessible, I have made them static inside MyUtils (which doesn't have any data/function member of its own). My code is thread safe before creating MyUtils.
My worry is, by making these inner classes staticwill they remain thread safe, when their multiple instances will exist across the files ? Or is their any bad implication am I missing due to making them static ?
Edit: I am not touching any shared variable inside the helper classes. My only concern was that will the instance of the static classes be thread safe (since they are static).
If you're asking whether these is any bad implication of going from:
public class Helper1 {}
...to:
public class MyUtils {
public static class Helper1 {}
}
Then no, there is not. The static keyword in this case is just "promoting" the nested inner class to a top-level class, so that you can instantiate it without needing an enclosing instance of MyUtils. Here is a passable article on the subject:
http://www.javaworld.com/javaworld/javaqa/1999-08/01-qa-static2.html
In essence, doing public static class X on a nested inner-class is the same as doing public class X in a standard top-level class.
There is no meaning to a "class" itself being thread-safe or not thread safe. Therefore, whether or not it is static is irrelevant.
When someone refers to a class being thread-safe or not thread-safe, they really mean that the functionalities provided by that class are thread-safe or not. Accordingly, it's what the inner classes do themselves that actually makes the difference.
There's nothing inherent about methods that make them unsafe to be reentrant. Problems arise when you start accessing shared variables, etc. So, for example, a member of the class accessed by the methods needs to be synchronized appropriately. But if the methods don't store any state, etc., then there's nothing stopping you from using them across multiple threads.
Hope that helps.
You will need to guard the access to help1 since this is an instance level (shared) variable.
While help2 is safe if you dont allow it to skip the method.
There is nothing special about the static classes and instance created out of it.
Same rules of thread safety applies to instances of static classes also which applies to normal cases.
static methods and inner classes don't have any access to the variables of their dynamic counter part, and consequently can't use monitors/synchronize on an instance of their parent class. Of course this doesn't mean that declaring them and using them is inherently non-thread safe. It's just that if you need to synchronize any of those static methods on an instance of the parent class, then you need to be sure that you synchronize/lock before entering them or else you must explicitly pass a reference to a parent instance into them.
I have got the answer. Making MyUtils an interface is more cleaner design, as I can get away with the static identifienr from the helper classes
I have just found a static nested interface in our code-base.
class Foo {
public static interface Bar {
/* snip */
}
/* snip */
}
I have never seen this before. The original developer is out of reach. Therefore I have to ask SO:
What are the semantics behind a static interface? What would change, if I remove the static? Why would anyone do this?
The static keyword in the above example is redundant (a nested interface is automatically "static") and can be removed with no effect on semantics; I would recommend it be removed. The same goes for "public" on interface methods and "public final" on interface fields - the modifiers are redundant and just add clutter to the source code.
Either way, the developer is simply declaring an interface named Foo.Bar. There is no further association with the enclosing class, except that code which cannot access Foo will not be able to access Foo.Bar either. (From source code - bytecode or reflection can access Foo.Bar even if Foo is package-private!)
It is acceptable style to create a nested interface this way if you expect it to be used only from the outer class, so that you do not create a new top-level name. For example:
public class Foo {
public interface Bar {
void callback();
}
public static void registerCallback(Bar bar) {...}
}
// ...elsewhere...
Foo.registerCallback(new Foo.Bar() {
public void callback() {...}
});
The question has been answered, but one good reason to use a nested interface is if its function is directly related to the class it is in. A good example of this is a Listener. If you had a class Foo and you wanted other classes to be able to listen for events on it, you could declare an interface named FooListener, which is ok, but it would probably be more clear to declare a nested interface and have those other classes implement Foo.Listener (a nested class Foo.Event isn't bad along with this).
Member interfaces are implicitly static. The static modifier in your example can be removed without changing the semantics of the code. See also the the Java Language Specification 8.5.1. Static Member Type Declarations
An inner interface has to be static in order to be accessed. The interface isn't associated with instances of the class, but with the class itself, so it would be accessed with Foo.Bar, like so:
public class Baz implements Foo.Bar {
...
}
In most ways, this isn't different from a static inner class.
Jesse's answer is close, but I think that there is a better code to demonstrate why an inner interface may be useful. Look at the code below before you read on. Can you find why the inner interface is useful? The answer is that class DoSomethingAlready can be instantiated with any class that implements A and C; not just the concrete class Zoo. Of course, this can be achieved even if AC is not inner, but imagine concatenating longer names (not just A and C), and doing this for other combinations (say, A and B, C and B, etc.) and you easily see how things go out of control. Not to mention that people reviewing your source tree will be overwhelmed by interfaces that are meaningful only in one class.So to summarize, an inner interface enables the construction of custom types and improves their encapsulation.
class ConcreteA implements A {
:
}
class ConcreteB implements B {
:
}
class ConcreteC implements C {
:
}
class Zoo implements A, C {
:
}
class DoSomethingAlready {
interface AC extends A, C { }
private final AC ac;
DoSomethingAlready(AC ac) {
this.ac = ac;
}
}
To answer your question very directly, look at Map.Entry.
Map.Entry
also this may be useful
Static Nested Inerfaces blog Entry
Typically I see static inner classes. Static inner classes cannot reference the containing classes wherease non-static classes can. Unless you're running into some package collisions (there already is an interface called Bar in the same package as Foo) I think I'd make it it's own file. It could also be a design decision to enforce the logical connection between Foo and Bar. Perhaps the author intended Bar to only be used with Foo (though a static inner interface won't enforce this, just a logical connection)
If you will change class Foo into interface Foo the "public" keyword in the above example will be also redundant as well because
interface defined inside another interface will implicitly public
static.
In 1998, Philip Wadler suggested a difference between static interfaces and non-static interfaces.
So far as I can see, the only difference in making an
interface non-static is that it can now include non-static inner
classes; so the change would not render invalid any existing Java
programs.
For example, he proposed a solution to the Expression Problem, which is the mismatch between expression as "how much can your language express" on the one hand and expression as "the terms you are trying to represent in your language" on the other hand.
An example of the difference between static and non-static nested interfaces can be seen in his sample code:
// This code does NOT compile
class LangF<This extends LangF<This>> {
interface Visitor<R> {
public R forNum(int n);
}
interface Exp {
// since Exp is non-static, it can refer to the type bound to This
public <R> R visit(This.Visitor<R> v);
}
}
His suggestion never made it in Java 1.5.0. Hence, all other answers are correct: there is no difference to static and non-static nested interfaces.
In Java, the static interface/class allows the interface/class to be used like a top-level class, that is, it can be declared by other classes. So, you can do:
class Bob
{
void FuncA ()
{
Foo.Bar foobar;
}
}
Without the static, the above would fail to compile. The advantage to this is that you don't need a new source file just to declare the interface. It also visually associates the interface Bar to the class Foo since you have to write Foo.Bar and implies that the Foo class does something with instances of Foo.Bar.
A description of class types in Java.
Static means that any class part of the package(project) can acces it without using a pointer. This can be usefull or hindering depending on the situation.
The perfect example of the usefullnes of "static" methods is the Math class. All methods in Math are static. This means you don't have to go out of your way, make a new instance, declare variables and store them in even more variables, you can just enter your data and get a result.
Static isn't always that usefull. If you're doing case-comparison for instance, you might want to store data in several different ways. You can't create three static methods with identical signatures. You need 3 different instances, non-static, and then you can and compare, caus if it's static, the data won't change along with the input.
Static methods are good for one-time returns and quick calculations or easy obtained data.