3

When I run some code (Shown later), I tell it to check if the string == "1", if it is, output "It's 1!", else, output the string.

Code:

double shirt3 = Math.random() * 9;
String shirt2 = Double.toString(shirt3);
char shirt1 = shirt2.charAt(0);
String shirt = Character.toString(shirt1);

if(shirt == "1") {
    System.out.println("It's 1!");
} else {
    System.out.println(shirt);
}

Output:

7
4
8
1
7
1
7
7
6
0

Makoto
  • 104,088
  • 27
  • 192
  • 230
cheese5505
  • 962
  • 5
  • 14
  • 30

6 Answers6

9

You need to use

if (shirt.equals("1"))
    ...

This will compare the actual contents of the String objects, rather than their identities.

Daniel Lubarov
  • 7,796
  • 1
  • 37
  • 56
5

You've made the Java beginner's mistake of using == to test String equality. Use the equals method instead.

The longer explanation is that the == operator in Java tests to see if two object references are identical; i.e. it tests if the left and right operands are the same object. But what you have is two distinct strings that contain the same sequence of characters. They are "equal" strings, but not the same object.

As a general rule of thumb, you should always use equals to compare strings.

(There are some situations where == will work, but you really need to understand what you are doing to be sure. And its is simply not worth the effort / risk in the vast majority of use-cases.)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
4

To check if two strings are the same in Java, use .equals():

"1" == new String("1") //returns false
"1".equals(new String("1")) //returns true

EDIT: Added new String("1") to ensure we are talking a new string.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
Christian Mann
  • 8,030
  • 5
  • 41
  • 51
  • 5
    Actually, `"1" == "1"` will return `true` due to string literals being interned. But if either of those two `"1"`s isn't a compile-time constant, that's when you'll see the issue. – cHao Apr 08 '12 at 04:59
3

Besides the fact you'll need to use the equals method to compare Strings in java

// it't allways a good idea to use constant.equals(...)
// to avoid possible NullPointerExceptions
if ("1".equals(shirt))
    ...

in your case you don't have to convert your character into a String you can also compare single characters. Does the same without creating an additional String object and you don't have to deal with the equals method.

if (shirt1 == '1')
        ...
andih
  • 5,570
  • 3
  • 26
  • 36
  • +1 for providing the best solution here: bypassing the re-stringification and the String issues altogether. :) – cHao Apr 08 '12 at 05:06
  • 2
    @cHao - this is the best solution, but it is more important that the OP understand why using `==` with String is wrong. – Stephen C Apr 08 '12 at 05:08
2

To compare strings use equals.

if(shirt.equals("1"))
     System.out.println("It's 1!");
    }else{
        System.out.println(shirt);
    }
Serdar Dogruyol
  • 5,147
  • 3
  • 24
  • 32
1

A more general rule is to not make code more complicated than it need to be.

int shirt = (int)(Math.random() * 10); // shirt numbers from 0 to 9.
if(shirt == 1) 
    System.out.println("It's 1!");
else 
    System.out.println(shirt);

This illustrated that == can be used to compare primitives. It can also be used to compare references, but not to compare the contents of objects.

Double d = 0.1;
Double e = 0.1;
System.out.println("(Double) 0.1 == (Double) 0.1 is " + (d == e));

double x = 0.1;
double y = 0.1;
System.out.println("0.1 == 0.1 is " + (x == y));

prints

(Double) 0.1 == (Double) 0.1 is false
0.1 == 0.1 is true

This shows that when comparing Double, like Strings, objects == doesn't compare contents.

One confusion in all this when a cache is used, as is the case for String literals. This means that values which are referenced in different places actually use the same object for performance reasons.

Integer d = 10;
Integer e = 10;
System.out.println("(Integer) 10 == (Integer) 10 is " + (d == e));

int x = 10;
int y = 10;
System.out.println("10 == 10 is " + (x == y));

prints

(Integer) 10 == (Integer) 10 is true
10 == 10 is true

The first example works because Java 5.0+ uses a cache of small integers. (The size of a small integer varies depending on command line parameters :} )

Integer d = -129;
Integer e = -129;
System.out.println("(Integer) -129 == (Integer) -129 is " + (d == e));

int x = -129;
int y = -129;
System.out.println("-129 == -129 is " + (x == y));

prints

(Integer) -129 == (Integer) -129 is false
-129 == -129 is true

As for strings, a string literal cache is used. Also the compiler will simplify constant expressions so strings written a different way can be the same.

final int one = 1;
int oneB = 1;
String a = "1";
String b = "" + 1;
String c = "" + one;
String d = "" + oneB;

System.out.println(a == b);
System.out.println(a == c);
System.out.println(a == d);

prints

true
true
false

The contents of each strings is the same, but oneB is not a constant, so the expression is evaluated at runtime and a different string is produced.

IMHO: Java attempts to hide details from developers and it would have been a better choice to make == call equals whereas you could have an operator === if you really wanted to compare actual references .

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130