Javaの文字列比較で気になった点

そういえば、何年か前に気になったことを思い出したのでメモしておきます。情報のソースを出すことができませんが、実験結果と考察だけ載せておきます。

実験

Javaにおいて、文字列比較をイコール演算子(==)で行うことはできません。これは常識です。しかし、このような場合は、成立してしまうようです。

class StringEqualsTest{
	public static void main(String[] args){
		String a = "aaa";
		String b = "aaa";
		if(a == b) System.out.println("match");
		else System.out.println("no-match");
	}
}
// > match

Javaにおいて、同じリテラル(定数)が存在する場合、それらは同じオブジェクトとして扱われます。そのため、このような実験結果になるわけです。

一方、こうやると期待通り(?)の結果を得ることができます。

class StringEqualsTest{
	public static void main(String[] args){
		String a = new String("aaa");
		String b = "aaa";
		if(a == b) System.out.println("match");
		else System.out.println("no-match");
	}
}
// > no-match

これは、文字列オブジェクトが新しく作成されるからですね。

次のようなことをやっても、違うオブジェクトと判断されます。

class StringEqualsTest{
	public static void main(String[] args){
		String a = "aaa";
		String b = "aaa";
		a = a + "";
		if(a == b) System.out.println("match");
		else System.out.println("no-match");
	}
}
// > no-match

これはなぜでしょうか。Javaにおいて内部的な文字列連結処理は、「ふたつの文字列をつなげた新しい文字列を格納するStringオブジェクトを作成する」となっているからです。そのため、文字列連結をループの中で過剰に何度も行うと、newを何度も行っていることと同意なので、パフォーマンスが下がります(オブジェクトの作成は手間がかかる処理なため)。

どうすればいいの

当然のごとく、String.equals()を使います。

class StringEqualsTest{
	public static void main(String[] args){
		String a = new String("aaa");
		String b = "aaa";
		if(a.equals(b)) System.out.println("match");
		else System.out.println("no-match");
	}
}
// > match

コメントを残す

メールアドレスが公開されることはありません。