1

I want to confirm if two String variable created is pointing to the same memory.The way I did it with normal class

Ideone a=new Ideone();
Ideone b=a;

System.out.println(a+" "+b);

Output

Ideone@106d69c Ideone@106d69c

The output produced here is not the exact memory address but it gave hex code which are same and by which I can say that they both are pointing to same memory address or values.

But in case of String

String a="helloworld";
String b="hello";
String c=b+"world";
System.out.println(a+" "+c);

Output

helloworld helloworld

Its the expected output and I know that a,b,c are created in the pool as they are compile-time constants and a and c do not point to same memory .But is there any way I can get the Object representation of string like String@23122 as to get the hex code of that object to confirm that a and c do not point to same memory? Because in case creating string by new String("helloworld") new memory is allocated to string.

I have searched it but dint find anything similar to my problem.

Thanks in advance.

singhakash
  • 7,891
  • 6
  • 31
  • 65

3 Answers3

2

As explained in the JLS

A string literal always refers to the same instance of class String.

But also, it depends on how you form the String object too.
Example: Calling new String("abcd") is like having string parameter "abcd" already, but still you force JVM to create a new String reference. Check More Info section...

As you said in your example, you cannot get the pointer id, but still you are able to get some unique string by calling toString() method, using that it kind of conforms they are unique. But the implementation of that toString is Object.toString()

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

So, it is HashCode.

As per the Hashcode contract, if two objects are equal, then that means their hashCode must be same, but it is not true vice versa.

The general contract of hashCode from spec is :

  • Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.

  • If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.

  • It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

So, either use == operator which will make identity/reference check or you must trust the JVM implementation that the String literals always point to unique reference, else the JVM is not following the specs.


More Info:

This is the example given in above mentioned JLS spec.

package testPackage;
class Test {
    public static void main(String[] args) {
        String hello = "Hello", lo = "lo";
        System.out.print((hello == "Hello") + " ");
        System.out.print((Other.hello == hello) + " ");
        System.out.print((other.Other.hello == hello) + " ");
        System.out.print((hello == ("Hel"+"lo")) + " ");
        System.out.print((hello == ("Hel"+lo)) + " ");
        System.out.println(hello == ("Hel"+lo).intern());
    }
}

class Other { static String hello = "Hello"; }

and the compilation unit:

package other;
public class Other { public static String hello = "Hello"; }

produces the output:

true true true true false true

This example illustrates six points:

  • Literal strings within the same class in the same package represent references to the same String object.

  • Literal strings within different classes in the same package represent references to the same String object.

  • Literal strings within different classes in different packages likewise represent references to the same String object.

  • Strings computed by constant expressions are computed at compile time and then treated as if they were literals.

  • Strings computed by concatenation at run time are newly created and therefore distinct.

  • The result of explicitly interning a computed string is the same string as any pre-existing literal string with the same contents.

rajuGT
  • 6,224
  • 2
  • 26
  • 44
  • 1
    I was confused which answer to choose because they all are good but what I like about you answer apart from other is that you hashCose javaspecs.Thanks – singhakash Oct 10 '15 at 19:54
1

I want to confirm if two String variable created is pointing to the same memory

You can check if any object references are pointing at the same object with the == operator. That's all you need:

boolean sameObject = (a == b);

is there any way I can get the Object representation of string like String@23122

Yes, if you really want that:

System.out.println(a.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(a)));

But that won't be useful, as two distinct objects may have the same hashcode. The hashcode is not necessarily the memory address, and usually isn't.

Boann
  • 48,794
  • 16
  • 117
  • 146
1

First, your method is wrong. You are counting on the string representation of classes that have not overridden the toString() method from Object.

The Object.toString method, if not overridden, returns a string that consists of the name of the class, @, and the hash code of the object. It's not its address, it has nothing to do with the address. Therefore, two objects with the same hash code will return the same string.

To demonstrate that, let's look at a small class that overrides equals and hashCode but doesn't override the toString method:

class MyInteger {
    int myInteger;

    public MyInteger(int myInteger) {
        this.myInteger = myInteger;
    }

    public int getInteger() {
        return myInteger;
    }
    @Override
    public boolean equals(Object obj) {
        if ( obj instanceof MyInteger ) {
            return myInteger == ((MyInteger)obj).myInteger;
        }
        return false;
    }

    @Override
    public int hashCode() {
        return myInteger;
    }
}

Now, let's try your method of distinguishing two different objects:

MyInteger int1 = new MyInteger(1004);
MyInteger int2 = new MyInteger(1004);
System.out.println(int1+" "+int2);

The result printed would be something like:

MyInteger@3ec MyInteger@3ec

But clearly int1 and int2 are pointing to two distinct objects, created explicitly with new!

So forget that method - it's not meaningful.


Now, how do you know two objects are distinct? Simple, compare the references with == or !=.

So if I tried above

System.out.println( int1 != int2 );

The result would be true.

It's the same for strings:

String a="helloworld";
String b="hello";
String c=b+"world";
String d="hello";
System.out.println("a refers to a different object than c? " + (a != c));
System.out.println("b refers to a different object than d? " + (b != d));

The results printed would be:

a refers to a different object than c? true
b refers to a different object than d? false
RealSkeptic
  • 33,993
  • 7
  • 53
  • 79