Domanda

Ho un costruttore come il seguente:

public Agent(){

    this.name = "John";
    this.id = 9;
    this.setTopWorldAgent(this, "Top_World_Agent", true);

}

Sto ricevendo un'eccezione puntatore null qui nella chiamata del metodo. Sembra che io stia usando 'this' come argomento nel metodo setTopWorldAgent. Rimuovendo questo metodo, tutto sembra a posto. Perché succede? Qualcun altro ha provato questo?

È stato utile?

Soluzione

Puoi passare questo ai metodi, ma setTopWorldAgent () non può essere astratto. Non è possibile effettuare una chiamata virtuale nel costruttore.

Nel costruttore di un oggetto, è possibile chiamare i metodi definiti in quell'oggetto o nelle classi base, ma non ci si può aspettare di chiamare qualcosa che verrà fornito da una classe derivata, poiché parti della classe derivata non sono costruite ancora. Mi sarei aspettato una sorta di errore del compilatore se setTopWorldAgent () fosse astratto.

In Java, puoi ottenere un comportamento sorprendente con il contraente e le classi derivate - ecco un esempio

http://en.wikipedia.org/wiki/Virtual_functions#Java_3

Se sei abituato a C # o C ++, potresti pensare che sia sicuro chiamare funzioni virtuali e non chiamare quelle sovrascritte. In Java, la chiamata virtuale viene effettuata anche se la classe derivata non è completamente costruita.

Se questo non è ciò che sta accadendo, presumibilmente, tutte le parti di cui ha bisogno setTopWorldAgent () - in caso contrario, è probabilmente uno dei membri di questo che deve essere inizializzato.

Modifica: pensato che fosse C #

Altri suggerimenti

Per curiosità, perché stai passando 'this' a una funzione membro della stessa classe? setTopWorldAgent () può usare 'this' direttamente. Non sembra che il tuo costruttore o setTopWorldAgent () siano statici, quindi non sono sicuro del motivo per cui potresti passare una funzione membro a cui ha già accesso.

A meno che non mi manchi qualcosa ...

Perché setTopWorldAgent dovrebbe avere this come argomento? Basato sull'invocazione, è un metodo di istanza, quindi potrebbe fare riferimento a this senza doverlo ricevere come parametro.

Penso più al punto, perché mai stai passando 'this' come parametro a un metodo in 'this'?

Quanto segue verificherebbe ciò che dici che ti sta accadendo e non ho problemi con esso.

public class Test {
  public Test() {
    this.hi(this);
  }
  public void hi(Test t) {
    System.out.println(t);
  }

  public static void main(String[] args) throws Exception {
    Test t = new Test();
  }
}

Dato che setTopWorldAgent sembra essere un metodo di istanza, perché lo stai passando comunque?

" questo " non dovrebbe mai essere nullo. Sei sicuro che l'eccezione venga generata a causa di ciò?

Un aspetto da tenere presente è che se il metodo è virtuale o chiama qualsiasi metodo virtuale, un metodo appartenente a una sottoclasse potrebbe essere eseguito prima dell'inizializzazione delle variabili della sottoclasse.

L'errore deve essere altrove perché il codice sopra funziona sicuramente, il riferimento null deve essere qualcos'altro.

Se il tuo agente sta implementando ITopWorldAgent, dovresti effettivamente farlo:


Agent agent = new Agent("John", 9);
agent.setTopWorldAgent(agent, "Top_World_Agent", true);

In caso contrario, perché stai impostando qualcosa nel modo in cui ti trovi?

Presumo che qualcosa nel metodo setTopWorldAgent stia usando un valore che non è stato ancora inizializzato nel costruttore.

this non è nullo, questo è certo. È stato assegnato.

Detto questo, non è necessario passare this al metodo, è automaticamente disponibile in tutti i metodi di istanza. Se il metodo è statico, è possibile trasformarlo in un metodo di istanza.

Le regole di Java affermano che non si dovrebbe mai passare 'questo' a un altro metodo dal suo costruttore, per la semplice ragione che l'oggetto non è stato completamente costruito. L'oggetto a cui fa riferimento potrebbe trovarsi in uno stato incoerente. Sono sorpreso che l'attuale riferimento "questo" sia nullo, ma per nulla sorpreso che alcuni membri di "questo" siano nulli quando viene passato a setTopWorldAgent e che il metodo genera l'eccezione a causa di ciò.

Di solito puoi evitare di passare "questo" dai costruttori purché in realtà non acceda a nessun membro o chiami metodi per esempio se vuoi impostare un riferimento a "questo" in un altro oggetto.

In questo caso, ovviamente, l'argomento non è necessario in quanto il metodo ha già un riferimento a "questo".

Sono contento che tu abbia avuto una risposta. Vorrei aggiungere che passare 'questo' come parametro può portare a problemi di concorrenza imprevisti. In pratica stai fornendo la possibilità che lo stato dell'oggetto sia manipolato in modo non sicuro da un codice potenzialmente non thread sicuro.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top