Question

J'ai un constructeur comme suit:

public Agent(){

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

}

Je reçois une exception de pointeur null ici dans l'appel de méthode. Cela semble être dû au fait que j'utilise 'this' comme argument dans la méthode setTopWorldAgent. En supprimant cette méthode, tout semble bien aller. Pourquoi cela arrive-t-il? Quelqu'un d'autre en at-il fait l'expérience?

Était-ce utile?

La solution

Vous pouvez transmettre cela aux méthodes, mais setTopWorldAgent () ne peut pas être abstrait. Vous ne pouvez pas effectuer d'appel virtuel dans le constructeur.

Dans le constructeur d'un objet, vous pouvez appeler des méthodes définies dans cet objet ou dans ces classes de base, mais vous ne pouvez pas vous attendre à appeler quelque chose qui sera fourni par une classe dérivée, car certaines parties de la classe dérivée ne sont pas construites. encore. Je m'attendrais à une sorte d'erreur de compilation si setTopWorldAgent () était abstrait.

En Java, vous pouvez obtenir un comportement surprenant avec le constructeur et les classes dérivées - voici un exemple

http://fr.wikipedia.org/wiki/functions_Virtuelles#Java_3

Si vous êtes habitué à C # ou C ++, vous pouvez penser qu’il est prudent d’appeler des fonctions virtuelles et non des fonctions remplacées. En Java, l’appel virtuel est effectué même si la classe dérivée n’est pas entièrement construite.

Si ce n'est pas ce qui se passe, toutes les parties nécessaires à setTopWorldAgent () sont probablement initialisées. Si ce n'est pas le cas, c'est probablement l'un des membres qui doit être initialisé.

Modifier: je pensais que c'était C #

Autres conseils

Par curiosité, pourquoi passez-vous "ceci" à une fonction membre de la même classe? setTopWorldAgent () peut utiliser 'this' directement. Il ne semble pas que votre constructeur ou setTopWorldAgent () soient statiques. Je ne sais donc pas pourquoi vous transmettriez à une fonction membre quelque chose à laquelle il a déjà accès.

À moins que je manque quelque chose ...

Pourquoi setTopWorldAgent aurait-il besoin de this en tant qu'argument? Basé sur l'invocation, il s'agit d'une méthode d'instance, qui peut donc référencer this sans avoir à le recevoir en tant que paramètre.

Je pense plus précisément au fait, pourquoi passez-vous 'this' comme paramètre à une méthode dans 'this'?

Ce qui suit pourrait tester ce que vous dites vous arrive et je n’ai aucun problème avec cela.

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();
  }
}

Étant donné que setTopWorldAgent semble être une méthode d'instance, pourquoi y passez-vous quand même?

"this" ne devrait jamais être nul. Êtes-vous sûr que l'exception est levée à cause de cela?

Il convient de se méfier du fait que si la méthode est virtuelle ou appelle une méthode virtuelle, une méthode appartenant à une sous-classe peut être exécutée avant que les variables de la sous-classe ne soient initialisées.

L'erreur doit être ailleurs car le code ci-dessus fonctionne, la référence null doit être autre chose.

Si votre agent implémente ITopWorldAgent, procédez comme suit:


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

Si non, alors pourquoi définissez-vous quelque chose comme vous êtes?

Je suppose que quelque chose dans la méthode setTopWorldAgent utilise une valeur qui n'a pas encore été initialisée dans votre constructeur.

this n'est pas nul, c'est certain. Il a été attribué.

Ceci étant dit, il n'est pas nécessaire de passer this dans la méthode, elle est automatiquement disponible dans toutes les méthodes d'instance. Si la méthode est statique, vous souhaiterez peut-être la refactoriser dans une méthode d'instance.

Les règles de Java stipulent que vous ne devez jamais transmettre "this" à une autre méthode de son constructeur, pour la simple raison que l'objet n'a pas été entièrement construit. L'objet qu'il référence peut être dans un état incohérent. Je suis surpris que la référence 'this' soit nulle, mais pas du tout surpris qu'un membre de 'this' soit nul lorsqu'il est passé à setTopWorldAgent et que la méthode lève l'exception à cause de cela.

Habituellement, vous pouvez vous passer du constructeur "this" à condition de ne pas accéder aux membres ni aux méthodes d'appel, par exemple, si vous souhaitez définir une référence à "this" dans un autre objet.

Dans ce cas bien sûr, l'argument n'est pas nécessaire car la méthode a déjà une référence à 'this'.

Content d’avoir une réponse. J'aimerais ajouter que le fait de passer ceci en tant que paramètre peut conduire à des problèmes inattendus de concurrence. Vous fournissez essentiellement la possibilité que l'état de l'objet soit manipulé de manière non sécurisée par un code potentiellement non-thread-safe.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top