The following class:
public class StaticMethodsDemo {
public static class A {
public static A make() { return new A(); };
}
public static class B extends A {
public static B make() { return new B(); };
}
public static class BPrime<T> extends A {
public static <T> BPrime<T> make() { return new BPrime<T>(); };
}
public static void main(String[] args) {
B.make();
// compiles under Sun JDK 1.6.0_20 but fails under Oracle JDK 1.7.0_01. Why?
BPrime.<Object>make();
}
}
compiles under Sun JDK 1.6.0_20 (Windows 64-bit, but shouldn't make a difference) but fails under Oracle JDK 1.7.0_01 (same platform) and OpenJDK 1.6.0_20 (Ubuntu) [1] with:
[ERROR] StaticMethodsDemo.java:[37,14] error: reference to make is ambiguous, both method make() in A and method <T>make() in BPrime match
Why? How does the generic parameter (which should be erased, no?) cause this apparent mismatch. Note that removing generics as follows:
...
public static class BPrime<T> extends A {
T val;
public static BPrime<?> make() { return new BPrime<Object>(); };
public void setT(T val) { this.val = val; }
}
public static void main(String[] args) {
B.make();
BPrime<Long> bprime = (BPrime<Long>) BPrime.make();
bprime.setT(Long.valueOf(10));
}
compiles and runs too (so the generics hack doesn't cause any weird runtime casting errors).
Issue 461: jclouds-core compilation fails using stock ubuntu openjdk
This Compile Error in Hidden module error message usually appears when there are dome 32-bit add-ins versions of office which are incompatible with the newer version. The most common reason behind this error is when some conditions come true:
After Installing the JDK and JRE adds the java command to your command line. You can verify this through the command prompt by the java -version command. In some cases, you need to restart your system after installing the JDK. You can use the JDK compiler to convert your Java text file into an executable program.
An archiver (jar) and many more. The Java Runtime Environment in JDK is usually called Private Runtime because it is separated from the regular JRE and has extra contents.
Setting up JDK in your development environment is super easy, just follow the below simple steps. Select the latest JDK version and click Download and add it to your classpath. Just check the JDK software is installed or not on your computer at the correct location, for example, at C:\Program Files\Java\jdk11.0.9.
Obviously, the javac6's behavior is reasonable, and javac7's not.
Unfortunately, according to the letter of the spec, javac7 is right.
This is due to the root of all evil in java - type erasure. The motivation is to generify collection APIs without breaking any old code that reference the old, non-generified collection API. For the purpose of brevity let's refer to it as the dumbest motivation.
When compiling BPrime.<Object>make()
, first javac needs to figure out the class containing the method. That is easily class B'
. ( http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.12.1 )
Then we need to know all methods in class B'
, including inherited ones. That comes down to whether method make()
(mb) in B'
hides method make()
(ma) in A
; which comes down to whether signature of mb is a subsignature of ma. ( http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.4.8 )
The existence of subsignature concept is also to serve the dumbest motivation. Otherwise we only need to worry about same signatures in determining overriding and hiding methods.
But that's not a problem this time. Per definition, mb is not a subsignature of ma, so ma is inherited in class B'
. So class B'
has two make()
methods.
Next step, is to identify potentially applicable methods. The rule says ( http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.12.2.1 )
If the method invocation includes explicit type parameters, and the member is a generic method, then the number of actual type parameters is equal to the number of formal type parameters.
That means ma is applicable to expression BPrime.<Object>make()
, because ma is not a generic method. What?!
The spec explains
The clause above implies that a non-generic method may be potentially applicable to an invocation that supplies explicit type parameters. Indeed, it may turn out to be applicable. In such a case, the type parameters will simply be ignored.
This rule stems from issues of compatibility and principles of substitutability. Since interfaces or superclasses may be generified independently of their subtypes, we may override a generic method with a non-generic one. However, the overriding (non-generic) method must be applicable to calls to the generic method, including calls that explicitly pass type parameters. Otherwise the subtype would not be substitutable for its generified supertype.
So this is also to serve the dumbest motivation, and we have to allow nonsense syntax like
System.<String,Integer>currentTimeMillis();
Then, both mb and ma are applicable, thus the ambiguity.
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