fork(1) download
  1. /* package whatever; // don't place package name! */
  2.  
  3. import java.util.*;
  4. import java.lang.*;
  5. import java.io.*;
  6.  
  7. /* Name of the class has to be "Main" only if the class is public. */
  8. class Ideone
  9. {
  10. static class Foo
  11. {
  12. private static String str = "abcd";
  13. static String getAbcdOfFoo() {
  14. return str;
  15. }
  16. }
  17.  
  18. static String getAbcd() {
  19. return "abcd";
  20. }
  21.  
  22. public static void main (String[] args) throws java.lang.Exception
  23. {
  24. // your code goes here
  25.  
  26. String a = "abcd";
  27. String b = "abcd";
  28. String c = new String("abcd");
  29. String d = "a" + ("b" + "c") + "d";
  30. String e = "ab";
  31. String f = "cd";
  32. String g = e + "cd";
  33. String h = e + f;
  34. String i = Ideone.getAbcd();
  35. String j = Ideone.Foo.getAbcdOfFoo();
  36. String k = Bar.getAbcdOfBar();
  37. String l = (new Baz()).getAbcdOfBaz();
  38. String m = "a".concat("bcd");
  39. String n, o;
  40. String p = (n = "ab") + (o = "cd");
  41. String q = "ab"; q += "cd";
  42.  
  43. System.out.println("== operator");
  44. System.out.println("a = \"abcd\"");
  45. System.out.println("a == b -> " + (a == b) + "\t // b = \"abcd\"");
  46. System.out.println("a == c -> " + (a == c) + "\t // c = new String(\"abcd\")");
  47. System.out.println("a == d -> " + (a == d) + "\t // d = \"a\" + (\"b\" + \"c\") + \"d\"");
  48. System.out.println("a == g -> " + (a == g) + "\t // e = \"ab\"; g = e + \"cd\"");
  49. System.out.println("a == h -> " + (a == h) + "\t // f = \"cd\"; h = e + f");
  50. System.out.println("a == i -> " + (a == i) + "\t // i = Ideone.getAbcd()");
  51. System.out.println("a == j -> " + (a == j) + "\t // j = Ideone.Foo.getAbcdOfFoo()");
  52. System.out.println("a == k -> " + (a == k) + "\t // k = Bar.getAbcdOfBar()");
  53. System.out.println("a == l -> " + (a == l) + "\t // l = (new Baz()).getAbcdOfBaz()");
  54. System.out.println("a == m -> " + (a == m) + "\t // m = \"a\".concat(\"bcd\")");
  55. System.out.println("a == p -> " + (a == p) + "\t // p = (n = \"ab\") + (o = \"cd\")");
  56. System.out.println("a == q -> " + (a == q) + "\t // q = \"ab\"; q += \"cd\"");
  57.  
  58. System.out.println();
  59. System.out.println("equals method");
  60. System.out.println("a = \"abcd\"");
  61. System.out.println("a.equals(b) -> " + a.equals(b) + "\t // b = \"abcd\"");
  62. System.out.println("a.equals(c) -> " + a.equals(c) + "\t // c = new String(\"abcd\")");
  63. System.out.println("a.equals(d) -> " + a.equals(d) + "\t // d = \"a\" + (\"b\" + \"c\") + \"d\"");
  64. System.out.println("a.equals(g) -> " + a.equals(g) + "\t // e = \"ab\"; g = e + \"cd\"");
  65. System.out.println("a.equals(h) -> " + a.equals(h) + "\t // f = \"cd\"; h = e + f");
  66. System.out.println("a.equals(i) -> " + a.equals(i) + "\t // i = Ideone.getAbcd()");
  67. System.out.println("a.equals(j) -> " + a.equals(j) + "\t // j = Ideone.Foo.getAbcdOfFoo()");
  68. System.out.println("a.equals(k) -> " + a.equals(k) + "\t // k = Bar.getAbcdOfBar()");
  69. System.out.println("a.equals(l) -> " + a.equals(l) + "\t // l = (new Baz()).getAbcdOfBaz()");
  70. System.out.println("a.equals(m) -> " + a.equals(m) + "\t // m = \"a\".concat(\"bcd\")");
  71. System.out.println("a.equals(p) -> " + a.equals(p) + "\t // p = (n = \"ab\") + (o = \"cd\")");
  72. System.out.println("a.equals(q) -> " + a.equals(q) + "\t // q = \"ab\"; q += \"cd\"");
  73.  
  74. }
  75. }
  76.  
  77. class Bar
  78. {
  79. private static String str = "abcd";
  80. static String getAbcdOfBar() {
  81. return str;
  82. }
  83. }
  84.  
  85. class Baz
  86. {
  87. private String str;
  88. Baz() {
  89. str = "abcd";
  90. }
  91. String getAbcdOfBaz() {
  92. return str;
  93. }
  94. }
Success #stdin #stdout 0.08s 380160KB
stdin
Javaにおいて同一のリテラル文字列は同一のインスタンスになる (無駄なメモリ割り当てを省くシステム)

==演算子での参照型変数の比較は
変数の参照先のメモリ番地(インスタンスの個別認識のためJavaマシンが割り当てた番号のようなもの)の比較になる
(参照型変数とはインスタンスの番号(メモリ番地)を保存してる変数なのである)
(int,byte,short,long,char,float,doubleなどはプリミティブ型であり参照型とは変数として性質が異なるので注意)

よって a と b はどちらも同一のリテラルのインスタンスを参照しているので a == b は true になる

一方、c は new String で新しいインスタンスを作ることを指示しているので
リテラルのインスタンスとは別のインスタンスが生成されることになるので
参照先のメモリ番地を比較する a == c は false となる

equalsメソッドでの比較はそれぞれのクラスの実装(オーバーライド)によって異なる
Stringクラスの場合は同一の文字列かどうかを比較する
全てのクラスの大元となるObjectクラスのequalsメソッドは==演算子の比較をするだけなので派生クラスでは必要に応じてequalsメソッドをオーバーライドしないといけない

d = "a" + ("b" + "c") + "d"
のようなリテラル同士の式は
コンパイラが事前計算して"abcd"に直してしまうので a == d が true になる

一方で h = e + f や p = (n = "ab") + (o = "cd") や q = "ab"; q += "cd" のように
一度でもリテラル文字列を変数に代入してしまうと上記の d ようなコンパイラによる事前計算をされることはないので新しいインスタンスが作られる

また、"a".concat("bcd") のようなメソッド呼び出しでもコンパイラによる事前計算はされないので新しいインスタンスが作られる
stdout
== operator
a = "abcd"
a == b -> true	 // b = "abcd"
a == c -> false	 // c = new String("abcd")
a == d -> true	 // d = "a" + ("b" + "c") + "d"
a == g -> false	 // e = "ab"; g = e + "cd"
a == h -> false	 // f = "cd"; h = e + f
a == i -> true	 // i = Ideone.getAbcd()
a == j -> true	 // j = Ideone.Foo.getAbcdOfFoo()
a == k -> true	 // k = Bar.getAbcdOfBar()
a == l -> true	 // l = (new Baz()).getAbcdOfBaz()
a == m -> false	 // m = "a".concat("bcd")
a == p -> false	 // p = (n = "ab") + (o = "cd")
a == q -> false	 // q = "ab"; q += "cd"

equals method
a = "abcd"
a.equals(b) -> true	 // b = "abcd"
a.equals(c) -> true	 // c = new String("abcd")
a.equals(d) -> true	 // d = "a" + ("b" + "c") + "d"
a.equals(g) -> true	 // e = "ab"; g = e + "cd"
a.equals(h) -> true	 // f = "cd"; h = e + f
a.equals(i) -> true	 // i = Ideone.getAbcd()
a.equals(j) -> true	 // j = Ideone.Foo.getAbcdOfFoo()
a.equals(k) -> true	 // k = Bar.getAbcdOfBar()
a.equals(l) -> true	 // l = (new Baz()).getAbcdOfBaz()
a.equals(m) -> true	 // m = "a".concat("bcd")
a.equals(p) -> true	 // p = (n = "ab") + (o = "cd")
a.equals(q) -> true	 // q = "ab"; q += "cd"