文字列のポイント
文字列は参照型
Javaの文字列はStringオブジェクトを使って表します。
本来文字列はchar型の配列を使って表現しますが、1文字しか扱えないため、煩雑な作業が必要になるため java.lang.Stringクラス を使います。
文字列は基本型(プリミティブ型)ではなく、参照型であることがポイントです。
*プリミティブ型は、一般的には言語の基本的なデータ型であり、より小さな単位に分解できない値を表します。数値や1文字、真偽値などが一般的なプリミティブ型の例です。
文字列の作成方法
文字列の作成方法は複数の方法が用意されています。
- Stringクラスのインスタンス化による方法:new String(“文字列”)で作成。この方法だと同じ文字列を作成してもStringオブジェクトを別に作成するのが特徴。
- ダブルクォテーションを使った文字列リテラル:“文字列” で作成。この方法だと同じ文字列を作成すると、同じStringオブジェクトを指し示すのが特徴
- String.valueOf(“文字列”) で作成。数値などを文字列に変更する場合に使用
String.valueOf()
がサポートする主な引数の型には次のものがあります。boolean
char
char[]
int
long
float
double
Object
byte
short
java.lang.Record
java.util.Optional
java.lang.constant.ConstantDesc
Stringオブジェクトはイミュータブルな性格を持ちます。一度作成した文字列を変更することはできません。
そのため、文字列の内容を変更するには別の参照を作る必要があります。
文字列の連結や変更操作が行われる場合、実際には新しいStringオブジェクトが作成され、元の文字列オブジェクトは変更されずに保持されます。
このイミュータブルな性質は、文字列の安全性やパフォーマンスの向上に寄与しますが、大量の文字列操作が行われる場合には注意が必要です。文字列の変更が頻繁に行われる場合は、StringBuilderやStringBufferなどの可変な文字列操作用のクラスを使用することが推奨されます。
Silver資格対策では、以下のコードの表示結果を正確に答えられるようにしましょう。
String s1 = new String("sample1"); String s2 = "sample1"; String s11 = new String("sample1"); String s21 = "sample1"; System.out.println(s1 == s11); // false System.out.println(s2 == s21); // true System.out.println(s1 == s2); // false System.out.println(s1.equals(s2)); // true System.out.println(s1.equals(s11)); //true System.out.println(s2.equals(s21)); //true
equals()メソッドのポイント
equals() メソッドは、Javaの Object クラスに定義されているメソッドで、すべてのクラスが暗黙的に Object クラスを継承するため、どのクラスでも使用することができます。ただし、Object クラスでのデフォルトの equals() メソッドの実装は、== 演算子と同じように、2つのオブジェクトが同じインスタンスであるかどうかを判定します。
String クラスでは、equals() メソッドがオーバーライドされており、2つの文字列が同じ内容を持つかどうかを比較します。
String str1 = new String("hello"); String str2 = new String("hello"); System.out.println(str1.equals(str2)); // trueを出力 System.out.println(str1 == str2); // falseを出力
要注意なのは、StringBuilder クラスでは equals() メソッドがオーバーライドされていないため、デフォルトの Object クラスの実装が使用され、2つの StringBuilder インスタンスが同じインスタンスであるかどうかを判定します。これは、StringBuilder の内容が同じであっても equals() メソッドは false を返すことを意味します。
StringBuilder の内容が同じであるかどうかを判定する場合は、toString() メソッドを使用して StringBuilder を String に変換し、equals() メソッドを使用することができます。
StringBuilder sb1 = new StringBuilder("hello"); StringBuilder sb2 = new StringBuilder("hello"); System.out.println(sb1.equals(sb2)); // falseを出力 System.out.println(sb1.toString().equals(sb2.toString())); // trueを出力
StringBuilder クラスのequals() メソッドをオーバーライドして、StringBuilder クラスが内容を基に等価性を判断するようにすることは技術的に可能です。ただし、StringBuilder はミュータブル(変更可能)で、主に文字列の効率的な結合や操作を行うためのクラスです。この性質上、頻繁に内容が変わる可能性があるため、内容に基づく等価性判定を行うのはあまり一般的ではありません。
java.lang.Stringクラスのメソッド
java.lang.Stringクラスのメソッドには次のようなものがあります。
charAt()
指定された文字列から、引数で指定された位置(0から始まる整数列)にある1文字を抜き出します。範囲外の番号を指定した場合は、例外がスローされます。
String str = "abcde"; System.out.print(str.charAt(4)); // e
replaceAll()
replaceAll()は第1引数に指定した文字列を第2引数の文字列に変更できますが、元データが変更されるわけではないので注意が必要です。変更された値が返されるだけです。これは文字列がイミュータブルな性格を持っているためです。
String str = "Hello world";
System.out.println(str.replaceAll("world", "tahara"));
System.out.println(str);
indexOf()
例外ではなく-1が返されるメソッド。引数で指定された文字が文字列のどの位置のものか文字に割り振られた番号が返されます。範囲外の場合は-1が返されます。例外の答えを引き出す、Java Silverの引っ掛け問題に出しやすそうです。
String str = "abcde";
System.out.println(str.indexOf("c")); // 2
System.out.println(str2.indexOf("bc")); // 1
System.out.println(str.indexOf("abcdef")); // -1
substring()
文字列から任意の文字列を抽出します。文字列の範囲は第1引数で開始位置、第2引数で終わりの位置をスライス指定します。特に終わりの指定は注意が必要で1つ先のindex番号の指定になります。
引数が一つの場合は、そこから先を抽出します。
String str = "abcde";
System.out.println(str.substring(1)); // bcde
System.out.println(str.substring(2, 4)); // cd
replace()
文字の置き換えに使用します。文字列の置き換えは1回ではなく、複数の対象の文字列がある場合は繰り返されます。String型だけでなくchar型にも使えますが、混在させてはダメ。
System.out.println(str1.replace("aa", "b")); // bb
System.out.println(str1.replace('a', 'b')); // bbbb
System.out.println(str1.replace("aa", 'b')); // コンパイルエラー String型とchar型の混在はだめ
length()
文字数を返すメソッド。半角も全角も1文字は1となります。
System.out.println(str.length());
startsWith()
文字列が引数で指定された文字で始まるか調べるメソッド。結果はbool値で返されます。
System.out.println(str.startsWith("a"));
endsWidth()
文字列が引数で指定された文字で終わるか調べるメソッド。結果はbool値で返されます。
System.out.println(str.endsWith("b"));
concat()
インスタンスが保持する文字列を引数として渡された文字列を連結する。+で繋ぐのと同じ効果があります。+で繋ぐ場合は、型を変更して繋ぐので注意。計算する場合は左から実行されるので挙動が違うので要注意。
System.out.println(str.concat("fg")); System.out.println(10+ 20 + "30" + 40); // 303040
StringBuilder()
StringBuilderクラスはデフォルトで16文字のバッファを持っています。ミュータブルな文字列を作成することができます。
StringBuilder str2 = new StringBuilder();
StringBuilder str3 = new StringBuilder("xyz");
StringBuilderクラスは、Java言語で文字列を扱うためのクラスの一つで、可変な文字列を操作するために使用されます。StringBuilderクラスは、Javaの標準ライブラリで提供されており、java.langパッケージに属しています。
StringBuilderクラスは、不変なStringクラスと異なり、文字列を変更することができます。また、文字列の結合や、文字列の挿入、削除、置換などの操作が可能です。これらの操作は、元の文字列を変更するのではなく、新しい文字列を作成するため、Stringクラスのような不変クラスよりも効率的に文字列を操作することができます。
StringBuilderクラスの主なメソッドには、以下のものがあります。
- append():文字列を末尾に追加します。
- insert():指定された位置に文字列を挿入します。
- delete():指定された範囲の文字列を削除します。
- replace():指定された範囲の文字列を置換します。
- substring():指定された範囲の部分文字列を取得します。
- toString():現在の文字列バッファの内容を文字列として返します。
StringBuilderクラスは、Java 5以降で導入された可変長引数の処理にも使用されます。可変長引数は、引数の数が可変であるメソッドを定義するための構文であり、StringBuilderクラスを使うことで、可変長の引数を1つの文字列に結合することができます。
バッファサイズの変更例
StringBuilder sb = new StringBuilder("Hello world."); System.out.println("Initial capacity: " + sb.capacity()); // 現在のバッファサイズを出力 sb.ensureCapacity(50); // バッファサイズを20文字に変更 System.out.println("New capacity: " + sb.capacity()); // 新しいバッファサイズを出力
append()
StringBuilderクラスが持つ文字列に新しい文字列を追加するメソッド
System.out.println(str2.append("ABC"));
reverse()
StringBuilderクラスが持つ文字列を反転するメソッド
System.out.println(str2.reverse());
System.out.println(str2.replace(1,3,"C"));
System.out.println(str3.indexOf("yz"));
null
null を+演算子で文字列と結合するとnullという文字列に変わります。
String str3 = null; str3 += "null";
System.out.println(str3); //nullnull
toString()について
toString()は、そのオブジェクトに関する情報の文字列を戻り値として返すメソッドです。
次のコードのように、そのまま使用すると「lesson1.Test1@251a69d7」のような値を返します。
class Test1 { // 何も定義してない }
public class Lesson1 {
public static void main(String[] args) {
Test1 t = new Test1();
System.out.println(t.toString());
}
}
表示結果
lesson1.Test1@251a69d7
次のように変更すると
class Test1 { @Override public String toString() { return "sample用に用意した文字列"; } } public class Lesson1 { public static void main(String[] args) { // TODO 自動生成されたメソッド・スタブ Test1 t = new Test1(); System.out.println(t.toString()); } }
sample用に用意した文字列
と表示されます。
本来よく使われるのは数値の文字列化に使用します。
String s = Integer.toString(100);
System.out.println(s.getClass().getSimpleName());
toString()のオーバーライド
toString()メソッドは、オブジェクトを文字列として表現するためのメソッドです。Javaの標準クラスライブラリでは、オブジェクトのtoString()メソッドは、クラス名とオブジェクトのハッシュコードを文字列として返します。オブジェクトのフィールドや状態を文字列として表現するために、このメソッドをオーバーライドすることができます。
例えば、以下のようにPersonクラスのtoString()メソッドをオーバーライドすることができます。
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
equals()メソッドのオーバーライド
equals()メソッドは、オブジェクトの等価性を比較するためのメソッドです。Javaでは、オブジェクトの等価性を判定するためには、equals()メソッドをオーバーライドする必要があります。equals()メソッドをオーバーライドする場合、一般的には、オブジェクトのフィールドを比較することになります。
例えば、以下のようにPersonクラスのequals()メソッドをオーバーライドすることができます。
public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof Person)) { return false; } Person other = (Person) o; return this.name.equals(other.name) && this.age == other.age; } }
public class Main2 { public static void main(String[] args) { Person p1 = new Person("Alice", 25); Person p2 = new Person("Bob", 30); Person p3 = new Person("Alice", 25); System.out.println("p1 equals p2: " + p1.equals(p2)); // false System.out.println("p1 equals p3: " + p1.equals(p3)); // true System.out.println("toString: " + p1.toString()); } }