Quand dois-je utiliser «ceci» dans une classe?

269

Je sais que cela thisfait référence à un objet actuel. Mais je ne sais pas quand j'ai vraiment besoin de l'utiliser. Par exemple, y aura-t-il une différence si j'utilise à la xplace de this.xcertaines méthodes? Peut être xfera référence à une variable qui est locale pour la méthode considérée? Je veux dire variable qui n'est vue que dans cette méthode.

Et alors this.method()? Puis-je l'utiliser? Dois-je l'utiliser. Si je l'utilise method(), ne sera-t-il pas, par défaut, appliqué à l'objet courant?

romain
la source

Réponses:

349

Le thismot-clé est principalement utilisé dans trois situations. Le premier et le plus courant est dans les méthodes de définition pour lever l'ambiguïté des références de variables. La seconde est quand il est nécessaire de passer l'instance de classe actuelle comme argument à une méthode d'un autre objet. Le troisième est comme un moyen d'appeler des constructeurs alternatifs à partir d'un constructeur.

Cas 1: Utilisation thispour lever l'ambiguïté des références de variable. Dans les méthodes de définition de Java, nous transmettons généralement un argument avec le même nom que la variable de membre privé que nous tentons de définir. Nous attribuons ensuite l'argument xà this.x. Cela indique clairement que vous affectez la valeur du paramètre "nom" à la variable d'instance "nom".

public class Foo
{
    private String name;

    public void setName(String name) {
        this.name = name;
    }
}

Cas 2: utilisation thiscomme argument passé à un autre objet.

public class Foo
{
    public String useBarMethod() {
        Bar theBar = new Bar();
        return theBar.barMethod(this);
    }

    public String getName() {
        return "Foo";
    }
}

public class Bar
{
    public void barMethod(Foo obj) {
        obj.getName();
    }
}

Cas 3: Utilisation thispour appeler des constructeurs alternatifs. Dans les commentaires, trinithis a correctement signalé une autre utilisation courante de this. Lorsque vous avez plusieurs constructeurs pour une même classe, vous pouvez utiliser this(arg0, arg1, ...)pour appeler un autre constructeur de votre choix, à condition de le faire dans la première ligne de votre constructeur.

class Foo
{
    public Foo() {
        this("Some default value for bar");

        //optional other lines
    }

    public Foo(String bar) {
        // Do something with bar
    }
}

J'ai également vu thisutilisé pour souligner le fait qu'une variable d'instance est référencée (sans la nécessité de la désambiguïsation), mais c'est un cas rare à mon avis.

William Brendel
la source
21
+1 Pour avoir mentionné que vous pouvez également passer ceci comme argument. ce n'est pas seulement utilisé pour la désambiguïsation de la portée.
Alex Jasmin
12
Bien sûr, il y a aussi à l' this(arg1, arg2, ...)intérieur d'un constructeur.
Thomas Eding
12
@Hazior: J'ai tendance à écrire une réponse courte, puis à y ajouter au fil du temps. Parfois, cela chevauche les réponses des autres, parfois non. Dans le cas de mon dernier montage, trinithis a souligné une autre utilisation courante de ce thisque j'avais oublié, alors je l'ai ajouté à ma réponse. Je ne vois rien de mal à cela parce que le résultat final est une meilleure réponse dans l'ensemble, ce qui est précisément l'objectif du SO. J'essaie également de donner du crédit dans la mesure du possible, comme je l'ai fait dans le cas des trinithis.
William Brendel
4
Vous avez des exemples pour les cas 1 et 3. Pouvez-vous donner un exemple du cas 2 où l'instance de classe actuelle est utilisée comme argument pour une méthode d'une autre classe?
dbconfession
4
@AStar Dans la plupart des bases de code Java avec lesquelles j'ai travaillé au fil des ans, thisn'est utilisé que si la désambiguïsation est vraiment nécessaire, comme dans mon exemple de setter ci-dessus. Les styles de codage et les "meilleures pratiques" peuvent varier considérablement en fonction de la personne à qui vous demandez, bien sûr, mais en général, je recommande de choisir des modèles raisonnables et de les respecter. La cohérence, même juste en interne dans une base de code unique, contribue grandement à la lisibilité et à la maintenabilité.
William Brendel
71

La deuxième utilisation importante de this(en plus de se cacher avec une variable locale comme de nombreuses réponses le disent déjà) est lors de l'accès à une instance externe à partir d'une classe non statique imbriquée:

public class Outer {
  protected int a;

  public class Inner {
    protected int a;

    public int foo(){
      return Outer.this.a;
    }

    public Outer getOuter(){
      return Outer.this;
    }
  }
}
Christopher Oezbek
la source
46

Vous n'avez besoin d'utiliser this- et la plupart des gens ne l'utilisent - que lorsqu'il existe une variable locale qui se chevauche avec le même nom. (Méthodes Setter, par exemple.)

Bien sûr, une autre bonne raison d'utiliser thisest qu'elle fait apparaître intellisense dans les IDE :)

froadie
la source
1
Mais vous devez ensuite revenir en arrière après l'avoir recherchée. La programmation est fatigante!
LegendLength
25

Le seul besoin d'utiliser le this.qualificatif est lorsqu'une autre variable dans la portée actuelle partage le même nom et que vous souhaitez faire référence au membre d'instance (comme William le décrit). En dehors de cela, il n'y a pas de différence de comportement entre xet this.x.

Adam Robinson
la source
3
Et si vous avez des noms en double, l'une de vos variables doit être renommée car elle est presque définitivement nommée incorrectement. Ou à tout le moins, pourrait être mieux nommé.
CaffGeek
3
@Chad: C'est une pratique courante dans les méthodes de définition de Java. Cependant, en dehors des méthodes de définition, vos déclarations sont généralement valables.
William Brendel
2
Vous pouvez également utiliser this.xpour rendre votre code un peu plus clair, la maintenabilité / lisibilité du code est également un facteur que vous devriez considérer ...
Bryan Rehbein
1
@Chad: Je ne suis pas assez d'accord avec enthousiasme. Seigneur, juste parce que "ceci". vous permet de donner à deux variables différentes le même nom, pourquoi voudriez-vous?
BlairHippo
2
@Blair: La lecture de votre réponse montre clairement que vous ne préférez pas cette pratique dans les méthodes de définition, mais beaucoup le font (je m'inclurais dans cette liste). Si j'ai une méthode de définition qui prend une valeur, la valeur transmise doit clairement être la "nouvelle" valeur, donc l'ajout de "nouveau" au nom de la variable semble ajouter une redondance inutile à l'API publique.
Adam Robinson
15

"this" est également utile lors de l'appel d'un constructeur à partir d'un autre:

public class MyClass {
    public MyClass(String foo) {
        this(foo, null);
    }
    public MyClass(String foo, String bar) {
        ...
    }
}
Benjamin
la source
11

this est utile dans le modèle de générateur.

public class User {

    private String firstName;
    private String surname;

    public User(Builder builder){
        firstName = builder.firstName;
        surname = builder.surname;
    }

    public String getFirstName(){
        return firstName;
    }

    public String getSurname(){
        return surname;
    }

    public static class Builder {
        private String firstName;
        private String surname;

        public Builder setFirstName(String firstName) {
            this.firstName = firstName;
            return this;
        }

        public Builder setSurname(String surname) {
            this.surname = surname;
            return this;
        }

        public User build(){
            return new User(this);
        }

    }

    public static void main(String[] args) {
        User.Builder builder = new User.Builder();
        User user = builder.setFirstName("John").setSurname("Doe").build();
    }

}
Kieren Dixon
la source
1
C'est le type de réponse que je voulais quand j'ai cherché et que je me suis retrouvé ici, mais vous n'avez aucune explication de votre code, donc la plupart des gens qui demandent "this" ne comprendront pas ce que "return new user (this);" signifie, comme je ne le fais pas ...
nckbrz
Le modèle Builder est utilisé pour spécifier clairement les paramètres lors de la construction. Au lieu d'avoir un nouvel utilisateur (chaîne, chaîne) sans moyen facile de dire quelle chaîne était laquelle, vous auriez un nouveau Builder (). SetFirstName ("Jane"). SetSurname ("Smith"). Build (). Vous renvoyez cela à partir des fonctions Builder.set ... () afin de pouvoir les enchaîner.
ChrisPhoenix
10

Il y a beaucoup de bonnes réponses, mais il y a une autre raison très mineure à mettre thispartout. Si vous avez essayé d'ouvrir vos codes source à partir d'un éditeur de texte normal (par exemple le bloc-notes, etc.), l'utilisation thisle rendra beaucoup plus clair à lire.

Imagine ça:

public class Hello {
    private String foo;

    // Some 10k lines of codes

    private String getStringFromSomewhere() {
        // ....
    }

    // More codes

    public class World {
        private String bar;

        // Another 10k lines of codes

        public void doSomething() {
            // More codes
            foo = "FOO";
            // More codes
            String s = getStringFromSomewhere();
            // More codes
            bar = s;
        }
    }
}

C'est très clair à lire avec n'importe quel IDE moderne, mais ce sera un cauchemar total à lire avec un éditeur de texte normal.

Vous aurez du mal à savoir où fooréside, jusqu'à ce que vous utilisez la fonction "trouver" de l'éditeur. Ensuite, vous crierez getStringFromSomewhere()pour la même raison. Enfin, après avoir oublié ce qui sest, cela bar = sva vous donner le coup de grâce.

Comparez-le à ceci:

public void doSomething() {
    // More codes
    Hello.this.foo = "FOO";
    // More codes
    String s = Hello.this.getStringFromSomewhere();
    // More codes
    this.bar = s;
}
  1. Vous savez, fooc'est une variable déclarée dans la classe externe Hello.
  2. Vous savez, getStringFromSomewhere()c'est aussi une méthode déclarée dans la classe externe.
  3. Vous savez que cela barappartient à la Worldclasse et qu'il ss'agit d'une variable locale déclarée dans cette méthode.

Bien sûr, chaque fois que vous concevez quelque chose, vous créez des règles. Ainsi , alors que la conception de votre API ou d'un projet, si vos règles sont « si quelqu'un ouvre tous ces codes sources avec un bloc - notes, il doit lui tirer dessus / elle - même dans la tête » , alors vous êtes tout à fait bien de ne pas faire cela .

I have
la source
grande réponse @Jai
Gaurav
La première raison de tirer serait d'écrire des classes avec plusieurs lignes de code de 10k, surtout si le code est déjà divisé en différentes classes qui n'ont pas besoin d'être imbriquées :)
LuCio
@LuCio Lol true xD
Jai
7

Sauf si vous avez des noms de variables qui se chevauchent, c'est vraiment juste pour plus de clarté lorsque vous lisez le code.

PouletMilkBomb
la source
1
Lorsque vous voyez constamment le thismot - clé quand il n'est pas nécessaire, c'est juste du code passe-partout qui rend le code plus difficile à lire.
AxeEffect
Je suis juste tombé sur un projet open source qui exige que tous les membres soient préfixés par «ceci». A part ça, le projet est très bien écrit mais je suis tenté de me lancer dans un débat religieux avec eux.
LegendLength
4
@AxeEffect Je sais que c'est vraiment vieux mais ... thisne rend PAS le code plus difficile à lire lmao.
Xatenev
4

La réponse de @William Brendel a fourni trois cas d'utilisation différents de manière agréable.

Cas d'utilisation 1:

La page de documentation Java officielle à ce sujet fournit les mêmes cas d'utilisation.

Dans une méthode d'instance ou un constructeur, il s'agit d'une référence à l'objet actuel - l'objet dont la méthode ou le constructeur est appelé. Vous pouvez faire référence à n'importe quel membre de l'objet actuel à partir d'une méthode d'instance ou d'un constructeur en utilisant ceci.

Il couvre deux exemples:

Utiliser ceci avec un champ et utiliser ceci avec un constructeur

Cas d'utilisation 2:

Autre cas d'utilisation qui n'a pas été cité dans cet article: thispeut être utilisé pour synchroniser l'objet actuel dans une application multithread pour protéger une section critique des données et méthodes.

synchronized(this){
    // Do some thing. 
}

Cas d'utilisation 3:

L'implémentation du modèle Builder dépend de l'utilisation de thispour renvoyer l'objet modifié.

Se référer à ce post

Garder le constructeur dans une classe distincte (interface fluide)

Ravindra babu
la source
2

Google a publié une page sur le site Sun qui en parle un peu.

Vous avez raison sur la variable; thispeut en effet être utilisé pour différencier une variable de méthode d'un champ de classe.

    private int x;
    public void setX(int x) {
        this.x=x;
    }

Cependant, je déteste vraiment cette convention. Donner deux variables différentes des noms littéralement identiques est une recette pour les bugs. Je préfère de beaucoup quelque chose comme:

    private int x;
    public void setX(int newX) {
        x=newX;
    }

Mêmes résultats, mais sans risque de bogue xauquel vous faites référence accidentellement alors que vous vouliez vraiment faire référence à la xplace.

Quant à son utilisation avec une méthode, vous avez raison sur les effets; vous obtiendrez les mêmes résultats avec ou sans. Pouvez-vous l'utiliser? Sûr. Devriez-vous l'utiliser? À vous de voir, mais étant donné que je pense personnellement que c'est une verbosité inutile qui n'ajoute aucune clarté (à moins que le code ne soit rempli de déclarations d'importation statiques), je ne suis pas enclin à l'utiliser moi-même.

BlairHippo
la source
4
Ce n'est pas une convention, c'est un mécanisme de délimitation du langage du programme. Ce que vous avez listé - utiliser newX (je préfère pX pour le paramètre x) est une convention.
Bill K
@Bill K: Je ne comprends pas la distinction que vous faites. Je peux choisir de nommer la variable d'entrée x, ou newX, ou pX, ou mangroveThroatWarblerX. Comment choisir de lui donner un nom identique à la variable qu'il ne définit PAS une convention, tout en ajoutant les conventions ARE "nouvelles" ou "p" ou "références Monty Python gratuites"?
BlairHippo
3
"Gratuitoud Monty Python References" n'est pas une convention, c'est la LOI.
Adam Robinson
+1: Pour cette raison, nous utilisons un standard de dénomination différent pour les arguments et les variables de méthode que pour les variables de classe. Nous abrégons les arguments / méthodes vars et utilisons des mots entiers pour les variables de classe / instance.
Lawrence Dol
1
Le résoudre en utilisant une convention de dénomination est, hmm, une convention. Le résoudre en utilisant une fonction de langue - je suppose que choisir de ne jamais utiliser cette fonction de langue ou de toujours l'utiliser serait une convention ... pour chaque fois que vous accédez à un membre serait une convention. Je suppose que cela n'a pas beaucoup d'importance, je déteste ça aussi.
Bill K
2

Voici les façons d'utiliser «ce» mot-clé en java:

  1. En utilisant this mot clé pour référencer les variables d'instance de classe actuelles
  2. Utilisation this()pour appeler le constructeur de classe actuel
  3. Utilisation d'un thismot clé pour renvoyer l'instance de classe actuelle
  4. Utilisation du thismot clé comme paramètre de méthode

https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html

roottraveller
la source
1

lorsqu'il y a deux variables, une variable d'instance et une autre variable locale du même nom, nous l'utilisons. pour référencer l'objet en cours d'exécution afin d'éviter le conflit entre les noms.

giri
la source
1

thisest une référence à l'objet courant. Il est utilisé dans le constructeur pour faire la distinction entre la variable de classe locale et la classe courante qui porte le même nom. par exemple:

public class circle {
    int x;
    circle(int x){
        this.x =x;
        //class variable =local variable 
    }
} 

thispeut également être utilisé pour appeler un constructeur à partir d'un autre constructeur. par exemple:

public class circle {
    int x;

    circle() { 
        this(1);
    }

    circle(int x) {
        this.x = x; 
    }
}
nouman shah
la source
0

Y aura-t-il une différence si j'utilise "x" au lieu de "this.x" dans certaines méthodes?

Généralement non. Mais cela fait parfois une différence:

  class A {
     private int i;
     public A(int i) {
        this.i = i; // this.i can be used to disambiguate the i being referred to
     }
  }

Si j'utilise simplement "method ()", ne sera-t-il pas, par défaut, appliqué à l'objet courant?

Oui. Mais si nécessaire, this.method()clarifie que l'appel est fait par cet objet.

amit
la source
0

thisn'affecte pas le code résultant - c'est l'opérateur de temps de compilation et le code généré avec ou sans sera le même. Lorsque vous devez l'utiliser, cela dépend du contexte. Par exemple, vous devez l'utiliser, comme vous l'avez dit, lorsque vous avez une variable locale qui masque la variable de classe et que vous voulez faire référence à une variable de classe et non à une variable locale.

edit: par "le code résultant sera le même" je veux dire bien sûr, quand une variable de portée locale ne cache pas celle appartenant à la classe. Donc

class POJO {
   protected int i;

   public void modify() {
      i = 9;
   }

   public void thisModify() {
      this.i = 9;
   }
}

le code résultant des deux méthodes sera le même. La différence sera si une méthode déclare une variable locale avec le même nom

  public void m() {
      int i;
      i = 9;  // i refers to variable in method's scope
      this.i = 9; // i refers to class variable
  }
doc
la source
0

En ce qui concerne les messages de William Brendel et la question dbconfessions , concernant le cas 2 . Voici un exemple:

public class Window {

  private Window parent;

  public Window (Window parent) {
    this.parent = parent;
  }

  public void addSubWindow() {
    Window child = new Window(this);
    list.add(child);
  }

  public void printInfo() {
    if (parent == null) {
      System.out.println("root");
    } else {
      System.out.println("child");
    }
  }

}

J'ai vu cela utilisé lors de la construction de relations parent-enfant avec des objets. Cependant, veuillez noter qu'il est simplifié par souci de concision.

Alija
la source
0

«Ce» mot-clé en java est utilisé pour référencer les objets de classe actuels.

Il y a 6 utilisations du mot-clé «this» en java

  1. Accès à la variable de niveau classe : principalement utilisé si la variable de niveau local et de classe est la même
  2. Accès aux méthodes de classe : c'est le comportement par défaut et peut être ignoré
  3. Pour appeler un autre constructeur de la même classe
  4. Utiliser le mot clé 'this' comme valeur de retour : pour renvoyer l'instance actuelle de la méthode
  5. Passer le mot-clé 'this' comme argument à la méthode Passer: pour passer l'instance de classe actuelle comme argument
  6. ce mot-clé comme argument au constructeur : pour passer l'instance de classe actuelle comme argument

réf: https://stacktraceguru.com/java/this-keyword-in-java

Rupesh Agrawal
la source
-8

Pour vous assurer que les membres de l'objet actuel sont utilisés. Dans les cas où la sécurité des threads est un problème, certaines applications peuvent modifier les valeurs de membre d'objets incorrectes, c'est pourquoi cela doit être appliqué au membre afin que la valeur de membre d'objet correcte soit utilisée.

Si votre objet n'est pas concerné par la sécurité des threads, il n'y a aucune raison de spécifier quelle valeur de membre d'objet est utilisée.

Myster October
la source
Ce n'est vraiment pas le cas. Je ne sais même pas à quel cas vous pensez, mais un exemple pourrait être utile pour comprendre ce que vous essayez de dire.
David Berger
1
Oui. Je sais que ce que vous expliquez concerne la sécurité des threads. Il n'y a pas de bonne réponse à cette question qui implique la sécurité des threads. Si "ceci" est nécessaire pour faire référence à l'objet correct, alors une fois qu'il le fait, la méthode ou l'attribut sera thread-safe si et seulement s'il est synchronisé. Si la référence est ambiguë, il sera ambigu que le multi-threading soit ou non un problème.
David Berger