Se il mio IDE è così intelligente, perché devo lanciare "clone ()"?


13

Il mio tipo IDE ( NetBeans ) controlla il mio Collectionsmentre sto scrivendo il codice. Ma allora, perché devo lanciare l'oggetto restituito di Object.clone()? Va bene Nessun danno nessun inganno. Ma ancora non capisco.

Il controllo del tipo, senza casting, Object.clone()non è possibile per l' oggetto restituito ? Il framework generics mi fa pensare che l'IDE potrebbe controllare il tipo di riferimenti a oggetti sul lato destro del segno " = " senza eseguire il casting mentre sto scrivendo? Non capisco

addendum Il
mio caso d'uso era solo che avevo un Calendarcampo privato , pubdate . Stavo per scrivere:

Calendar getPubdate() {
    return pubdate;
}

ma c'è il rischio che l'invoker possa modificare il mio pubdate , quindi ho restituito una copia:

Calendar getPubdate() {
    return (Calendar) pubdate.clone();
}

Quindi, mi chiedevo perché dovevo fare il cast pubdate.clone(). La firma del metodo ha il tipo proprio lì. NetBeans dovrebbe essere in grado di capirlo. E NetBeans sembrava fare qualcosa di simile riguardo a Collections.


5
Un breve esempio di codice (!) Sarebbe utile.
Doc Brown,

78
L'IDE è separato dalla lingua stessa, quindi come Netbeans intelligente non ha alcun effetto su come funziona Java la lingua.
Jacques

7
Si noti, a causa di tornare tipo di covarianza, si consiglia di tornare MyObjectda clone(), piuttosto che Object- questo rimuove l'intero problema. Si consiglia inoltre di non utilizzare mai clone()(articolo Java effettivo n. 11).
Boris il ragno

L'enfasi della tua domanda su I o su "cast" clone () "' ? Perché la domanda risultante dalla prima potrebbe effettivamente essere una domanda molto migliore rispetto alla seconda.
user541686

Quando leggo il titolo della domanda, l'unica cosa a cui penso è this.clone()sull'oggetto programmatore, specialmente la notte di mercoledì dopo l'uscita di Tue. Scusa ma devo scrivere questo commento ... Perché l'IDE intelligente non può risolvere tutti i bug per noi LOL
Mai

Risposte:


53

perché devo lanciare l'oggetto restituito di Object.clone()?

Perché ritorna Object.

Il framework generics mi fa pensare che l'IDE potrebbe controllare il tipo di riferimenti a oggetti sul lato destro del segno " = " senza eseguire il casting mentre sto scrivendo? Non capisco

Object.clone non è generico.

Se i generici fossero esistiti quando è clonestato progettato, probabilmente sarebbe stato così (usando il polimorfismo limitato da F):

interface Cloneable<T extends Cloneable<T>> {
  T clone();
}

Se Java avesse una funzionalità MyType, potrebbe apparire così:

interface Cloneable {
  this clone();
}

Ma Generics non esisteva quando è Object.clonestato progettato e Java non ha MyTypes, quindi la versione non sicura di tipo Object.cloneè ciò con cui dobbiamo lavorare.


Ho appena capito che la funzione IDE che mi ha confuso era la compilazione in background? Voglio dire, questo è ciò che abilita il completamento del codice e il controllo automatico del tipo con generici? Personalmente, preferirei ritardare il controllo del tipo fino a una compilazione esplicita. Ma adoro il completamento del codice.
konishiki

1
@konishiki con Java 8 (e in qualche misura Java 7) tipo di inferenza , al fine di fornire qualsiasi tipo di assistenza, le esigenze IDE ai tipi di Infer. Ciò richiede una compilazione parziale. Prima dell'inferenza del tipo, non è necessaria alcuna compilazione per il completamento automatico.
Boris the Spider

@BoristheSpider Grazie mille per il tuo feedback! Ho sicuramente bisogno di fare qualche altro test / pensiero. davvero apprezzato.
konishiki

Perché dovresti passare original?
Clashsoft,

@Clashsoft: stupido thinko adattando l'ovvia versione della programmazione funzionale. Grazie.
Jörg W Mittag,

26

Questa non è una caratteristica di alcun IDE, ma della definizione della lingua.

Un IDE ti aiuta a usare un linguaggio di programmazione in modo più efficiente, non cambia la semantica di quel linguaggio. Ciò significa che un helper editor potrebbe inserire automaticamente un cast quando è ovvio quale desideri, ma non può semplicemente infrangere le regole del linguaggio e fingere che il codice che non viene compilato sia valido.

Modifica È vero che un IDE può raggruppare il proprio compilatore, e in effetti molti lo fanno esattamente, ad esempio per una migliore segnalazione degli errori con più informazioni interne nell'albero di analisi parziale. Tuttavia, sarebbe una pessima idea lasciare che questo compilatore interno implementasse una semantica del linguaggio diversa rispetto all'SDK ufficiale, poiché ciò significherebbe che il codice che funziona nello sviluppo può misteriosamente iniziare a fallire quando installato in produzione - producendo problemi che sono per definizione non- debuggable!


Questo è quello che è successo: sono abbastanza sicuro che il completamento del codice sia una funzione IDE (eseguita tramite reflection). E il controllo automatico del tipo di cui stavo parlando avviene nell'IDE (tramite compilation in background). Spero che sia quello che sta succedendo.
konishiki,

1
L'IDE può infrangere molto facilmente tutte le regole delle specifiche del linguaggio e compilare comunque il codice. So che sia NetBeans che Eclipse usano i loro compilatori, per esempio. Quindi in quei casi IDE e compilatore sono effettivamente la stessa cosa. Non dire che è una buona idea, ma i compilatori C certamente lo fanno sempre.
MichaelS,

@MichaelS Le specifiche del linguaggio C sono progettate per consentire variazioni significative tra le implementazioni, in modo che diversi fornitori possano scegliere tra diversi approcci possibili e aggiungere funzionalità extra. Ciò crea varie aree di ambiguità nelle specifiche, che sono necessarie per consentire tali variazioni. Il nome "C" non è un marchio registrato, quindi nessuno controlla l'uso del termine. Le specifiche Java sono progettate per eliminare quanta più ambiguità possibile, e Java è un marchio registrato e il titolare del marchio impone che possa essere utilizzato solo in implementazioni conformi.
Jules,

Gli IDE moderni necessitano comunque di un compilatore. I suggerimenti per il completamento del codice richiedono che il codice prima del cursore venga analizzato. E certamente con generici (o modelli C ++) che richiedono un compilatore completo, non solo un parser.
MSalters

3

È dovuto alla firma del tipo del metodo Object.clone. La firma del tipo indica che il metodo restituirà un oggetto di tipo Object.

protected Object clone() throws CloneNotSupportedException

Le raccolte utilizzeranno i cosiddetti tipi generici per sostituire automaticamente il tipo di casting.

Quindi se hai questo codice:

List<Integer> ints = Arrays.asList(1,2,3);
int x = ints.get(0);`

il compilatore aggiungerà i cast per te dietro le quinte, quindi il codice sarebbe effettivamente:

List ints = Arrays.asList(1,2,3);
int x = (Integer)ints.get(0);

0

Per completezza, a partire da Java 5, sono consentiti tipi di ritorno covarianti . Quindi puoi scrivere quanto segue:

public MyObject implements Cloneable {
  @Override
  public MyObject clone() {
    try {
      return (MyObject)super.clone();
    } catch (CloneNotSupportedException e) {
      throw new AssertionError();
    }
  }
}

Con questo, il seguente codice è legale:

MyObject original = new MyObject();
MyObject clone = original.clone();
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.