Perché possiamo trasmettere un'interfaccia Java a * qualsiasi * classe non finale?
Domanda
import java.util.Collection;
public class Test
{
public static void main(String[] args)
{
Collection c = null;
Test s = null;
s = (Test) c;
}
}
Nell'esempio di codice sopra, sto lanciando un oggetto di raccolta su un oggetto Test. (ignorando il puntatore null). Test ha nessuna relazione con Collection, tuttavia questo programma supererà tutti i controlli in fase di compilazione.
Mi chiedo perché sia ??così. La mia ipotesi è che le interfacce vengano ignorate perché troppo complicate. Non hanno un super-tipo comune e ogni classe può implementare diverse interfacce, quindi la gerarchia di classi / interfacce sarebbe troppo complicata per effettuare ricerche efficienti?
A parte questo motivo, però, sono perplesso. Qualcuno lo sa ?!
Soluzione
" non finale " è una parola chiave qui. Potresti avere un'altra lezione
public class Test2 extends Test implements Collection
la cui istanza finirà per essere assegnata a s
rendendo un cast perfettamente legale.
Altri suggerimenti
Perché una sottoclasse di Test
può potenzialmente essere anche un sottotipo di Collection
! Le specifiche del linguaggio sono progettate per essere un po 'flessibili per consentire cast che possono essere verificati in fase di esecuzione.
Possiamo vederlo da una prospettiva diversa: qualsiasi classe non finale può essere trasmessa a QUALSIASI interfaccia
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; }
}