Consider the following code:
public class Outer<T> {
public class Inner{
}
public static <T> Outer<T>.Inner get(){
Object o = new Object();
return (Outer<T>.Inner)o;
}
public static void main(String[] args) throws Exception {
Outer.<String>get();
}
}
This code compiles successfully in Eclipse, but fails to compile in javac
:
Outer.java:10: ')' expected
return (Outer<T>.Inner)o;
^
Outer.java:10: ';' expected
return (Outer<T>.Inner)o;
^
Outer.java:10: illegal start of expression
return (Outer<T>.Inner)o;
^
3 errors
Is this a bug in javac
or Eclipse?
If I change the cast to (Outer.Inner)o
it compiles, although there is a warning:
Eclipse:
Outer.Inner is a raw type. References to generic type Outer<T>.Inner should be parameterized
javac:
Outer.java:10: warning: [unchecked] unchecked conversion
found : Outer.Inner
required: Outer<T>.Inner
return (Outer.Inner)o;
^
1 warning
Javac version: 1.6.0_21
They are accessed using the enclosing class name. For example, to create an object for the static nested class, use this syntax: OuterClass.
Unlike a class, an inner class can be private and once you declare an inner class private, it cannot be accessed from an object outside the class.
Inner classes have their disadvantages. From a maintenance point of view, inexperienced Java developers may find the inner class difficult to understand. The use of inner classes will also increase the total number of classes in your code.
Inner Classes 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.
I have found that this is a bug in the javac compiler that has since been fixed. JDK 7b100 compiles this fine.
See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6665356
The most amusing thing is that, unless there is something that I miss about Java generics, both
return (Outer<T>.Inner) o;
And
return (Outer.Inner) o;
Both compile to the same bytecode.
The problem for the first line happens at parsing - meaning that javac and Eclipse do not use the same parser for Java source code. You should ask a question about what differences there are between Eclipse JDT's java parser and javac's. (Or post a bug at Eclipse).
If you insist on keeping that behaviour (I would suggest refactoring Inner
to a static inner class), you could use @SuppressWarning with a field assignation (in order to restrict the @SuppressWarning to the smallest scope possible).
@SuppressWarnings({"rawtypes","unchecked"})
Outer<T>.Inner casted = (Outer.Inner)o;
return casted;
EDIT: OK, I believe I got it - Eclipse's JDT parses the Java code before passing it to the compiler - and their parser can make sense of such a cast, while (at least your and my version of) javac
's cannot. (And after that, Eclipse directly passes the parsed code to compilation). Before filing a bug, look at how the last version of Java 6 behaves.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With