I want to declare an interface inside an inner class, which shows compiler error message "inner classes cannot have static declarations".
public class Apple {
//...
public class InnerApple{
//...
public interface InnerInterface{
//Error: inner classes cannot have static declarations
}
}
}
Does it mean interface is actually static in Java?
I'm using Java 1.7. Thanks!!
An interface is always static - in a sense that there cannot be any dependency to another instance.
Having two levels of inner declarations is quite uncommon, but if it is intended I would expect that at least InnerApple is static:
public class Apple {
public static class InnerApple{
public interface InnerInterface{
//this does not cause an error
}
}
}
In most cases the keyword static of inner classes is omitted. If so this class may contain dependencies to a surrounding instance (and not only to the class as static inner classes do).
Yes, member interfaces are implicitly static. Section 8.5.1 of the JLS states:
A member interface is implicitly static (§9.1.1).
For it not to be static, the interface must be top-level, with no enclosing class or interface.
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()
All variables inside of interface are public static and final.
So if I declare a nested class inside an interface will it also become static and final?
Interface I
{
class c
{
static void m(){ }
}
}
Lets find out. Lets create structure like:
interface Interface{
class Foo{}
}
Now we can test:
System.out.println("static: " + Modifier.isStatic(Interface.Foo.class.getModifiers()));
System.out.println("final: " + Modifier.isFinal(Interface.Foo.class.getModifiers()));
which prints:
static: true
final: false
So nested classes are implicitly static, but not final.
We can confirm it also by adding class Bar extends Foo{} to our interface. final classes can't be extended but since such code compiles fine it means Foo is not final.
Classes nested inside interfaces behave like static classes nested inside classes, in the sense that you do not need to have an instance of an outer class in order to construct an instance of a nested class. According to Java Language Specification, §8.1.3:
8.1.3 Inner Classes and Enclosing Instances
[...] A member class of an interface is implicitly static (§9.5) so is never considered to be an inner class.
However, these classes are not final, unless you explicitly designate them as such. This makes sense, because classes that implement an interface may need an opportunity to extend nested classes defined inside the interface.
I am trying to find out, if it is possible to create anonymous inner class as abstract. I thought, that it doesn't make sense because I am trying to create instance of the abstract class, but the message from compiler confused me:
Class 'Anonymous class derived from Test' must either be declared abstract or implement abstract method 'method()' in Test
Code:
abstract class Test{
abstract void method();
}
Test o = new Test(){};
If it is possible to declare anonymous class as abstract, please let me know how to do that.
I would be greatful for answer.
See JLS Sec 15.9.5 (emphasis mine):
15.9.5. Anonymous Class Declarations
An anonymous class declaration is automatically derived from a class instance creation expression by the Java compiler.
An anonymous class is never abstract (§8.1.1.1).
An anonymous class is always implicitly final (§8.1.1.2).
An anonymous class is always an inner class (§8.1.3); it is never static (§8.1.1, §8.5.1).
you can't and does not make sense to declare anonymous class as abstract class as anonymous are used as local class only once.
i think you are getting this error because of similar issue Class must either be declared abstract or implement abstract method error
As quoted by Andy Turner the answer to your question is NO.
However I think you wanted to know something different.
Why do you get this compiler message?
Well the compiler is a bit misleading here. It offers two possible solutions based on that you are declaring a class (that anonymous class) and then also want to create an instance of that class:
make the derived class (which an anonymous class always is) abstract,
this is fine for normal and inner classes but it is not possible for anonymous classes, so the compiler should not suggest it in the first place
implement all methods and have no abstract methods in your anonymous class declaration
So to solve your actual problem: simply implement method() so your anonymous class declaration contains no more abstract methods
abstract class Test{
abstract void method();
}
Test o = new Test()
{
void method()
{
// do something
};
};
Now everything is declared and the compiler should not complain any more.
I have the following situation.
package A;
class SampleClass
{
static interface sampleInterface
{
....
}
}
Now when I try to import the sampleInterface from another package , jDev says 'access not allowed'. What could be the problem?
Currently, the interface is seen as package-private (there's no visibility modifier, so that's the default). Place public on the outer class and the interface, and it will become visible to other classes.
Just be careful - if you get caught in a situation where you have to do this:
public class Alpha extends Alpha.IAlpha {
public void doNothing();
public static interface IAlpha {
public void doNothing();
}
}
...you'll have an issue with cyclic inheritance, and your class won't compile. In fact, you won't be able to use the interface at all.
Keep these rules in mind for exposing interfaces, classes, or enums:
If you only need an inner class, interface, or enum for that particular object, then it's fine to declare it as static.
If you need a class, interface, or enum accessible from anywhere but that object, then it's best to move it out of the inner class, and into its own file.
In general, interfaces are seen as APIs to conform by - there's really no benefit in having them as nested unless the scope of them is extremely narrow.
Change visibility of the class and the interface to public. It will work for sure.
When you declare a class without a access specifier it is by package-default. This means you can access that class in that package only.
If you want to access class from another package, make class public, i.e.
public class SampleClass
Similarly, in your case, as you want to access the Interface as well, you have to make that interface public as well.
This will solve your problem.
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.