TL; DR, bu bir derleyici hatasıdır.
Devralındığında belirli bir geçerli yönteme veya varsayılan bir yönteme öncelik verecek bir kural yoktur. İlginç bir şekilde, kodu değiştirdiğimde
interface ConsumerOne<T> {
void accept(T a);
}
interface ConsumerTwo<T> {
void accept(T a);
}
interface CustomIterable<T> extends Iterable<T> {
void forEach(ConsumerOne<? super T> c); //overload
void forEach(ConsumerTwo<? super T> c); //another overload
}
iterable.forEach((A a) -> aList.add(a));
ifadesi Eclipse bir hata üretir.
Başka bir aşırı yük bildirilirken arabirimdeki forEach(Consumer<? super T) c)
yöntemin hiçbir özelliği Iterable<T>
değişmediğinden, Eclipse'nin bu yöntemi seçme kararı yöntemin hiçbir özelliğine dayanamaz (tutarlı bir şekilde). Hala tek miras alınan yöntem, hala tek default
yöntem, hala tek JDK yöntemi, vb. Bu özelliklerin hiçbiri yine de yöntem seçimini etkilememelidir.
Bildirgenin şu şekilde değiştirildiğine dikkat edin:
interface CustomIterable<T> {
void forEach(ConsumerOne<? super T> c);
default void forEach(ConsumerTwo<? super T> c) {}
}
ayrıca “belirsiz” bir hata üretir, bu nedenle uygulanabilir aşırı yüklenmiş yöntemlerin sayısı da önemli değildir, sadece iki aday olsa bile, default
yöntemlere karşı genel bir tercih yoktur .
Şimdiye kadar, sorun iki uygulanabilir yöntem olduğunda ve bir default
yöntem ve bir miras ilişkisi söz konusu olduğunda ortaya çıkıyor gibi görünüyor , ancak bu daha fazla kazmak için doğru yer değil.
Ancak, örneğinizin yapılarının derleyicideki farklı uygulama koduyla işlenebileceği anlaşılabilir, biri hata yaparken diğeri hata göstermez.
a -> aList.add(a)
Bir olan dolaylı olarak yazılmış aşırı çözünürlük için kullanılamaz lambda ifade. Buna karşılık, aşırı yüklenmiş yöntemlerden bir eşleştirme yöntemi seçmek için kullanılabilen açık(A a) -> aList.add(a)
bir şekilde yazılmış bir lambda ifadesidir, ancak tüm yöntemlerin tam olarak aynı işlevsel imzayla parametre türlerine sahip olması nedeniyle burada yardımcı olmaz (burada yardımcı olmamalıdır). .
Karşı örnek olarak,
static void forEach(Consumer<String> c) {}
static void forEach(Predicate<String> c) {}
{
forEach(s -> s.isEmpty());
forEach((String s) -> s.isEmpty());
}
işlevsel imzalar farklıdır ve açık bir şekilde lambda ifadesi kullanmak doğru yöntemi seçmeye yardımcı olabilirken örtük olarak yazılan lambda ifadesi yardımcı olmaz, bu nedenle forEach(s -> s.isEmpty())
bir derleyici hatası üretir. Ve tüm Java derleyicileri bu konuda hemfikir.
Yöntem de aşırı yüklendiğinden aList::add
belirsiz bir yöntem başvurusu olduğuna dikkat edin add
, bu nedenle bir yöntem seçmeye de yardımcı olamaz, ancak yöntem başvuruları yine de farklı kodlarla işlenebilir. Kesin bir geçiş aList::contains
ya da değişen List
için Collection
yapmak, add
kesin, benim Eclipse kurulumda sonucunu değiştirmedi (kullandım 2019-06
).