web-dev-qa-db-fra.com

Comment obtenez-vous la "référence d'objet" d'un objet dans Java lorsque toString () et hashCode () ont été remplacés?

Je voudrais imprimer la "référence d'objet" d'un objet dans Java à des fins de débogage. À savoir, pour vous assurer que l'objet est identique (ou différent) en fonction de la situation.

Le problème est que la classe en question hérite d'une autre classe, qui a été annulée à la fois par toString () et par hashCode (), ce qui me donne généralement l'identifiant.

Exemple de situation: Exécution d’une application multithread où I (pendant le développement) souhaite vérifier si tous les threads utilisent ou non la même instance d’un objet ressource.

98
Nicolai

Que comptez-vous faire exactement avec cela (ce que vous voulez faire fait une différence avec ce que vous devez appeler).

hashCode , tel que défini dans les JavaDocs, dit:

Dans la mesure du possible, la méthode hashCode définie par la classe Object renvoie des entiers distincts pour des objets distincts. (Ceci est généralement implémenté en convertissant l'adresse interne de l'objet en un entier, mais cette technique d'implémentation n'est pas requise par le langage de programmation Java ™.)

Donc, si vous utilisez hashCode() pour savoir s'il s'agit d'un objet unique en mémoire, ce n'est pas un bon moyen de le faire.

System.identityHashCode fait ce qui suit:

Retourne le même code de hachage pour l'objet donné que celui qui serait renvoyé par la méthode par défaut hashCode (), que la classe de l'objet donné substitue ou non hashCode (). Le code de hachage pour la référence null est zéro.

Ce qui, pour ce que vous faites, ressemble à ce que vous voulez ... mais ce que vous voulez faire peut ne pas être sûr, en fonction de la manière dont la bibliothèque est mise en œuvre.

100
TofuBeer

Voici comment je l'ai résolu:

Integer.toHexString(System.identityHashCode(object));
48
Nicolai

Double égal à == vérifiera toujours en fonction de l'identité de l'objet, indépendamment de l'implémentation de hashCode ou de l'égal de ces objets. Bien sûr, assurez-vous que les références d'objet que vous comparez sont volatile (dans une JVM 1.5 +).

Si vous devez réellement avoir le résultat Object toString d'origine (bien que ce ne soit pas la meilleure solution pour votre exemple d'utilisation), la bibliothèque Commons Lang a une méthode ObjectUtils.identityToString (Object) qui fera ce que vous voulez. vouloir. De la JavaDoc:

public static Java.lang.String identityToString(Java.lang.Object object)

Obtient le toString qui serait produit par Object si une classe ne remplaçait pas toString elle-même. null retournera null.

 ObjectUtils.identityToString(null)         = null
 ObjectUtils.identityToString("")           = "Java.lang.String@1e23"
 ObjectUtils.identityToString(Boolean.TRUE) = "Java.lang.Boolean@7fa"
8
noahlz

Vous ne pouvez pas faire ce que vous voulez en toute sécurité, car hashCode () par défaut peut ne pas renvoyer l'adresse et a déjà été mentionné. Plusieurs objets avec le même hashCode sont possibles. Le seul moyen d'accomplir ce que vous voulez consiste à redéfinir la méthode hashCode () pour les objets en question et à garantir qu'ils fournissent tous des valeurs uniques. Une autre question est de savoir si cela est réalisable dans votre situation.

Pour mémoire, j'ai rencontré plusieurs objets avec le même hashcode par défaut dans un ordinateur IBM VM s'exécutant sur un serveur WAS. Nous avons rencontré un problème: les objets placés dans un cache distant étaient écrasés à cause des problèmes suivants: C’était une révélation pour moi à ce moment-là puisque j’imaginais que le hashcode par défaut était également l’adresse mémoire des objets.

4
Robin

Ajoutez un identifiant unique à toutes vos instances, c.-à-d.

public interface Idable {
  int id();
}

public class IdGenerator {
  private static int id = 0;
  public static synchronized int generate() { return id++; }
}

public abstract class AbstractSomething implements Idable {
  private int id;
  public AbstractSomething () {
    this.id = IdGenerator.generate();
  }
  public int id() { return id; }
}

Étendre de AbstractSomething et interroger cette propriété. Sera en sécurité à l'intérieur d'une seule machine virtuelle (en supposant qu'aucune partie ne joue avec des chargeurs de classe pour contourner la statique).

2
bruceg

nous pouvons simplement copier le code de tostring de la classe d'objet pour obtenir la référence de chaîne

class Test
{
  public static void main(String args[])
  {
    String a="nikhil";     // it stores in String constant pool
    String s=new String("nikhil");    //with new stores in heap
    System.out.println(Integer.toHexString(System.identityHashCode(a)));
    System.out.println(Integer.toHexString(System.identityHashCode(s)));
  }
}
0
Nikhil Jaitak