2016-04-27 25 views
7

Quando si crea un metodo predefinito in Java 8, alcuni metodi Object non possono essere richiamati dal metodo predefinito. Per esempio:Perché alcuni metodi Object non possono essere richiamati dai metodi predefiniti?

interface I { 
    default void m() { 
     this.toString(); // works. 
     this.clone(); // compile-time error, "The method clone() is undefined for the type I" 
     this.finalize(); // same error as above. 
    } 
} 

Sembra che clone() e finalize() sono gli unici metodi da Object che non sono consentiti. Coincidently, questi sono gli unici metodi di Object che sono protetti, ma questa domanda riguarda in particolare i metodi predefiniti, in quanto verranno ereditati dalle classi che si estendono java.lang.Object. Qual è la ragione di questo?

+1

Possibile duplicato di [Perché il metodo clone() è protetto in java.lang.Object?] (Http://stackoverflow.com/questions/1138769/why-is-the-clone-method-protected-in- java-lang-object) – Sean

+1

@SPrasha Non sono d'accordo. Questa domanda non ha nulla a che fare con il motivo per cui non è richiamabile nel metodo predefinito di un'interfaccia. – rgettman

risposta

8

Non è un caso che i metodi protected da Object non siano disponibili in un metodo default in un'interfaccia.

Section 9.2 of the JLS stati:

Se un'interfaccia non ha superinterfacce dirette, quindi l'interfaccia dichiara implicitamente un metodo public abstract membro m con la firma s, tipo di ritorno r, e clausola throws t corrispondente ad ogni metodo public istanza m con la firma s, il tipo di ritorno r e la clausola di lancio t dichiarata in Object, a meno che un metodo abstract con la stessa firma, lo stesso tipo di ritorno e un compat La clausola throws è dichiarata esplicitamente dall'interfaccia.

Un'interfaccia non erediterà nulla da Object, ma sarà implicitamente dichiarare tutti publicObject metodi. Questo non include i metodi protected. Questo spiega perché non è possibile chiamare clone e finalize; non sono dichiarati in un'interfaccia.

+0

Interessante. Non ero a conoscenza del fatto che le interfacce non ereditassero da 'Object' quando dichiarano il metodo' default'. Tuttavia, non è possibile chiamare direttamente un metodo 'default'; deve essere richiamato su un oggetto la cui classe implementa direttamente o indirettamente l'interfaccia. Quella classe senza dubbio erediterà da 'Object'. Pertanto, dovrebbe essere sicuro per consentire questo. Interessante decisione di progettazione. –

+2

@RaffiKhatchadourian Giusto per chiarire, le interfacce ** mai ** ereditano da 'Object', indipendentemente dal fatto che esista o meno un metodo predefinito. Semplicemente no. Il problema con l'ereditare da 'Object' è che per esempio il metodo' toString() 'potrebbe essere sovrascritto da qualsiasi classe che implementa' I', quindi quale implementazione dovrebbe essere scelta allora? Quello ereditato dall'interfaccia o quello della classe che implementa l'interfaccia? – biziclop

+0

@biziclop Se è il caso che le interfacce ** mai ** ereditano da 'Object', allora perché' Object o = i; 'dove' i' ha un tipo di interfaccia in fase di compilazione legale? In realtà, questo sembra correlato a http://stackoverflow.com/questions/6056124/do-interfaces-inherit-from-object-class-in-java. –