Warum können wir werfen einen Java-Schnittstelle * jede * Nicht-final-Klasse?
Frage
import java.util.Collection;
public class Test
{
public static void main(String[] args)
{
Collection c = null;
Test s = null;
s = (Test) c;
}
}
In dem Codebeispiel oben, ich bin Gießen eines Sammelobjekt an ein Testobjekt. (Unter Vernachlässigung der Null-Zeiger). Test hat nicht Beziehung auch immer zu Sammlung, noch dieses Programms werden alle Prüfungen kompilieren Zeit passieren.
Ich frage mich, warum das so ist. Meine Vermutung ist, dass Schnittstellen ignoriert werden, weil sie zu kompliziert sind. Sie haben keinen gemeinsamen Super-Typ und jede Klasse kann mehrere Schnittstellen implementieren, so dass die Klasse / Interface-Hierarchie wäre zu kompliziert, effizient zu suchen?
Anders als diesem Grund dachte ich bin ratlos. Weiß jemand,?!
Lösung
"Nicht-final" ist ein Schlüsselwort hier. Sie können eine andere Klasse haben
public class Test2 extends Test implements Collection
, deren Instanz wird am Ende zugeordnet ist ein gegossenes vollkommen legal s
zu machen.
Andere Tipps
Da eine Unterklasse von Test
möglicherweise auch einen Subtyp von Collection
sein kann! Die Sprachspezifikation ist so konzipiert, ein wenig flexibel sein Abgüsse zu ermöglichen, die zur Laufzeit überprüft werden können.
Wir können es von einem anderen Interessenten anzuzeigen: jede nicht final class kann auf jede beliebige Oberfläche gegossen werden
import java.util.function.Predicate;
public class Test {
public static void main(String[] args) {
Predicate check;
try {
/*It's ok to cast to ANY interface because the Base class is not final.
Java compiler allows it because some class may extend it
and implement the predicate interface.
So java compiler can check it only at runtime time not compile time.
*/
check = (Predicate)(new Base());
/*
Java compiler doesn’t allow it because the BaseFinal is final.
And it means that no one can extend it and implement interface Predicate.
So java compiler can check it at compile time.
*/
//check = (Predicate)(new BaseFinal());
} catch (ClassCastException e) {
System.out.println("Class Cast Exception");
}
check = (Predicate)(Base)(new Child());
}
}
final class BaseFinal {};
class Base {}
class Child extends Base implements Predicate {
public boolean test(Object t) { return true; }
}