Pertimbangkan dua kelas dan antarmuka berikut:
public class Class1 {}
public class Class2 {}
public interface Interface1 {}
Mengapa panggilan kedua untuk mandatory
memanggil metode kelebihan beban dengan Class2
, jika getInterface1
dan Interface1
tidak memiliki hubungan dengan Class2
?
public class Test {
public static void main(String[] args) {
Class1 class1 = getClass1();
Interface1 interface1 = getInterface1();
mandatory(getClass1()); // prints "T is not class2"
mandatory(getInterface1()); // prints "T is class2"
mandatory(class1); // prints "T is not class2"
mandatory(interface1); // prints "T is not class2"
}
public static <T> void mandatory(T o) {
System.out.println("T is not class2");
}
public static <T extends Class2> void mandatory(T o) {
System.out.println("T is class2");
}
public static <T extends Class1> T getClass1() {
return null;
}
public static <T extends Interface1> T getInterface1() {
return null;
}
}
Saya mengerti bahwa Java 8 merusak kompatibilitas dengan Java 7:
$ /usr/lib/jvm/java-8-openjdk-amd64/bin/javac -source 1.7 -target 1.7 *java; /usr/lib/jvm/java-8-openjdk-amd64/bin/java Test
warning: [options] bootstrap class path not set in conjunction with -source 1.7
1 warning
T is not class2
T is not class2
T is not class2
T is not class2
Dan dengan Java 8 (juga diuji dengan 11 dan 13):
$ /usr/lib/jvm/java-8-openjdk-amd64/bin/javac *java; /usr/lib/jvm/java-8-openjdk-amd64/bin/java Test
T is not class2
T is class2
T is not class2
T is not class2
Jawaban:
Aturan inferensi tipe telah menerima perbaikan yang signifikan di Jawa 8, terutama inferensi tipe target telah banyak diperbaiki. Jadi, sedangkan sebelum Java 8 situs metode argumen tidak menerima inferensi, default ke tipe terhapus (
Class1
untukgetClass1()
danInterface1
untukgetInterface1()
), di Java 8 tipe yang paling spesifik yang berlaku disimpulkan. JLS untuk Java 8 memperkenalkan bab baru Bab 18. Ketik Inferensi yang hilang di JLS untuk Java 7.Jenis yang paling spesifik untuk diaplikasikan
<T extends Interface1>
adalah<X extends RequiredClass & BottomInterface>
, di manaRequiredClass
kelas dibutuhkan oleh konteks, danBottomInterface
merupakan tipe terbawah untuk semua antarmuka (termasukInterface1
).Catatan: Setiap tipe Java dapat direpresentasikan sebagai
SomeClass & SomeInterfaces
. KarenaRequiredClass
ini adalah sub-tipe dariSomeClass
, danBottomInterface
adalah sub-tipe dariSomeInterfaces
,X
adalah sub-tipe dari setiap tipe Java. Oleh karena itu,X
adalah tipe bawah Java.X
cocok dengan keduapublic static <T> void mandatory(T o)
danpublic static <T extends Class2> void mandatory(T o)
metode tanda tangan karenaX
adalah tipe bawah Jawa.Jadi, menurut §15.12.2 ,
mandatory(getInterface1())
memanggilmandatory()
metode kelebihan beban paling spesifik , yangpublic static <T extends Class2> void mandatory(T o)
karena<T extends Class2>
itu lebih spesifik daripada<T>
.Inilah cara Anda dapat secara eksplisit menentukan
getInterface1()
parameter tipe untuk membuatnya mengembalikan hasil yang cocokpublic static <T extends Class2> void mandatory(T o)
dengan tanda tangan metode:Jenis yang paling spesifik untuk diaplikasikan
<T extends Class1>
adalah<Y extends Class1 & BottomInterface>
, di manaBottomInterface
adalah tipe terbawah untuk semua antarmuka.Y
cocokpublic static <T> void mandatory(T o)
dengan tanda tangan metode, tetapi tidak cocokpublic static <T extends Class2> void mandatory(T o)
dengan tanda tangan metode karenaY
tidak diperpanjangClass2
.Begitu
mandatory(getClass1())
panggilanpublic static <T> void mandatory(T o)
metode.Berbeda dengan dengan
getInterface1()
, Anda tidak bisa secara eksplisit menentukangetClass1()
parameter tipe untuk membuatnya mengembalikan hasil yang cocokpublic static <T extends Class2> void mandatory(T o)
dengan tanda tangan metode:sumber