2013-02-06 13 views
6

Ho le seguenti classiCambiare l'interfaccia senza ricompilare classe che implementa

public abstract interface X 
{ 
    public abstract void f() throws java.io.IOException; 
} 


public class Y implements X 
{ 
    public void f() throws java.io.IOException 
    { 
     throw new java.ioIOException("Hello"); 
    } 

    public static void main(String [] args) 
    { 
     X x = new Y(); 
     try 
     { 
      x.f(); 
     } 
     catch (IOException e) 
     { 
      System.out.println("Caught"); 
     } 
    } 

} 

Ora compilo entrambi e ottenere X.class e Y.class.

Ora posso cambiare X per rimuovere la tiri

public abstract interface X 
{ 
    public abstract void f(); 
} 

Ovviamente se io ricompilare sia X & Y, la compilazione di Y fallirà

Y.java:4: f() in Y cannot implement f() in X; overridden method does not throw j 
ava.io.IOException 

Tuttavia, quello che se solo ricompilare X.java & mantieni il mio Y.class che è stato compilato con il vecchio X.java.

Cosa succede in questo caso: è ben definito?

Oppure rientra nella categoria di indefinito - cioè può succedere di tutto?

Ci sono delle garanzie - se lo sto eseguendo sempre sotto Java 1.6.32 sotto Windows, posso contare sul fatto che non accada nulla di brutto?

Aggiornamento: aggiornato perché alcune risposte dicevano che avrei ricevuto un IncompatibleClassChangeError in fase di esecuzione. Ma io no.

Procedura

1) raccogliere sia X.java e Y.java come sopra. Esegui Y.

uscita: Catturato

2) Variazione X.java commentare la tiri. Ricompilare X.java. Do not ricompilare Y.java.

Run Y

uscita: Catturato

Sono in esecuzione di Java su Windows 7

Compiler

javac 1.6.0_35 

Runtime

java version "1.6.0_35" 
Java(TM) SE Runtime Environment (build 1.6.0_35-b10) 
Java HotSpot(TM) Client VM (build 20.10-b01, mixed mode, sharing) 
+0

1. Perché non ci provi? 2. Direi che il "eccesso" genera nell'implementor anche un messaggio di errore in fase di compilazione. – TheBlastOne

+1

@TheBlastOne Ho provato. Funziona bene. Può essere che tu non abbia letto correttamente il mio post - l'errore del tempo di compilazione avverrà solo se ricompilerò Y. – user93353

risposta

3

Questo è una limitazione in Java in questo momento. Crea un'interfaccia secondaria che estenda l'interfaccia corrente e sovrascriva il metodo senza l'eccezione se ne hai davvero bisogno. In generale, si parla di "modifica binaria" e si verifica un collegamento interrotto quando il codice viene eseguito ed è ben definito nel JLS (c'è un intero capitolo su di esso, JLS 13, si desidera specificamente JLS 13.5).

Modifica: dopo ulteriori indagini, risulta che mi sono sbagliato. Da JLS 13.4.21:

Le modifiche alla clausola di throws di metodi o costruttori non rompere la compatibilità con i file binari pre-esistenti; queste clausole sono verificate solo al momento della compilazione.

Tuttavia, mi raccomando ancora di non farlo poiché significa che un'eccezione controllata può essenzialmente diventare deselezionata in fase di esecuzione.

+0

Perché il downvote? – Brian

+0

Java 8 'default' non aiuterà qui. La rimozione dell'eccezione non sta creando un nuovo metodo. Sta cambiando un metodo esistente in un modo che sarebbe incoerente con la sua interfaccia. –

+0

@StephenC Risulta comunque che ho sbagliato completamente, vedere la mia modifica. – Brian