Stringクラスの必要性と利便性
ActionCommandや,これからネットワーク越しのメッセージなどを扱う時に,JavaのStringクラスやその類似クラスによる文字列操作は避けて通れない.
が,JavaのStringは他言語の標準ライブラリに比べて異様なまでに便利であり,標準で備えていない機能はないとも言えるぐらいである.ActionCommandやネットワークメッセージに使う基本的な機能のみを紹介し,あとはJavaの公式ドキュメントを紹介する.
Java公式のStringクラスの仕様 https://docs.oracle.com/javase/jp/8/docs/api/java/lang/String.html
コンストラクタ
String myString = new String("初期化の際の文字列");
で最初から「初期化の際の文字列」が入ったStringのインスタンスが生成できる.
同じ文字列かどうかを見る
myString.euqals("比較したい文字列");
を実行すると,同じ文字列(同じオブジェクトインスタンスではない)ならばtrueが,そうでないならfalseが返ってくる.これを利用し,if文の中に突っ込むことで,これまでActionCommand等の判定を行ってきた.
文字列同士の連結
String firstString = new String("FirstString");
String secondString = new String("SecondString");
が予め存在する時,以下の方法で文字列連結ができる.
String newString = firstString + secondString;
String newString = firstString.concat(secondString);
が,これはfor文やイテレータなど,配列に入っている文字列をぶん回す際には使えないので,StringBufferクラスやStringBuilderクラスを使って以下の方法がある.
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(firstString);
stringBuffer.append(secondString);
String newString = stringBuffer.toString();
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(firstString);
stringBuilder.append(secondString);
String newString = stringBuilder.toString();
速度としてはStringBuilderクラスを使う方法が一番早く(プラス演算子の1万倍ぐらい早い),次いでStringBufferクラスを使う方法が早い(プラス演算子の5千倍ぐらい早い)に.プラス演算子やconcatは極端に遅いが,足さなければならないStringのインスタンスが少なく量が決まっている場合にはコードが短くなるという利点がある.
スプリッタ文字を指定した切り分け
String givenCommand = "OSC/Desafinado/Toalka/Pikka";
という文字列があった場合,「/」を取り除いて各要素を含んだ配列にし,その配列を用いて状態分岐ツリーを作りたい状況が,特にアクションコマンドやネットワークメッセージを利用している場合に多発する.
String[] splittedCommand = givenCommand.split("/", 0)
と書いてやると,この場合は,"OSC", "Desafinado", "Toalka", "Pikka"という文字列(String型)を要素に持つ配列splittedCommandが生成される.分割に使う文字は
2番目の引数は「最大分割数」なのだが,2番目の引数を省略,もしくは0にすることにより全ての要素の分割が行われる.
2番目の引数に「-1」を指定することにより,空白の要素を除くことができる.例えば,
String givenCommand = "OSC,,Desafinado,Talka,,";
という文字列が与えられた時,2番目の引数が0の場合,
givenCommand.split(",", 0);
配列の中身は,"OSC", "", "Desafinado", "Talka", "", ""
となり,空白のStringが入ってしまう.そこで-1を第2引数に指定し,
givenCommand.split(",", -1);
とすると,出力の配列の中身は,"OSC", "Desafinado", "Talka"
の3要素のみとなる.
文字列から数字型へ変換
数字から文字列への変換は,単に"文字列" + i
のように+
演算子で既存の文字列につなぎ合わせることで可能である他,
int number = 1356;
String value = new String(number);
のように,Stringのコンストラクタに数字を渡す方法でも可能である.
またIntegerクラスのオブジェクトインスタンスを作り,インスタンス関数toString()
を実行することでも,数字の文字列を得られる.
int number = 1356;
Integer myInteger = new Integer(number);
String value = myInteger.toString();
問題は逆で,文字列として受け取った「数字」を演算可能にするために,例えば整数型などに入れる場合である.整数型ならInteger
クラスのstaticメソッドparseInt()
を使う.
String commandNumberInString = "1356";
int commandNumberInInteger = Integer.parseInt(commandNumberInString);
と書くと,int型に変換される.
parseInt()
はstaticメソッドであり,クラスのインスタンスを作っていなくても使うことができる.
StringとJTextFieldを使った実例
前項の複数のボタンでテキストフィールドの内容を書き換えるプログラムを,改造し,テキストフィールドに入力された「,」で区切られた2つの数字を足したり引いたりするプログラム.
import processing.awt.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
void setup(){
size(640, 480);
Canvas canvas = (Canvas)surface.getNative();
JLayeredPane layeredPane = (JLayeredPane)canvas.getParent().getParent();
JTextField textField = new JTextField("3,4");
textField.setBounds(10, 360, 620, 20);
MyButtonListener myButtonListener = new MyButtonListener();
myButtonListener.setTextField(textField);
JButton button1 = new JButton("Add");
button1.setBounds(10, 390, 100, 20);
JButton button2 = new JButton("Sub");
button2.setBounds(120, 390, 100, 20);
button1.setActionCommand("add_two_values");
button1.addActionListener(myButtonListener);
button2.setActionCommand("sub_two_values");
button2.addActionListener(myButtonListener);
layeredPane.add(textField);
layeredPane.add(button1);
layeredPane.add(button2);
// ボタンリスナーのインナークラス
// 例によって,インナークラスではなく別ファイルに分離することもできる
class MyButtonListener implements ActionListener {
JTextField textField;
void setTextField(JTextField textField){
// テキストフィールドを操作するために,変数に実体を登録しておく
this.textField = textField;
}
@Override
public void actionPerformed(ActionEvent e){
String actionCommand = e.getActionCommand();
if(actionCommand.equals("add_two_values")){
// 足し算ボタンが押された時
// JTextFieldクラスのインスタンスが持つgetText関数を使うと
// その時点でテキストフィールドに入力されている文字列を
// String型のインスタンスとして取り出すことができる
String givenString = textField.getText();
// 試しに表示してみる
System.out.println(givenString);
// テキストフィールドに入っていた2つの数字は,間を「,」で区切って入力する
// 一つの文字列として入って来ているので,「,」でsplitする
String[] givenValues = givenString.split(",", -1);
// Integerクラスが持つ静的関数parseInt関数に「数字の文字列」を入れると
// int型に変換してくれる
int firstValue = Integer.parseInt(givenValues[0]);
int secondValue = Integer.parseInt(givenValues[1]);
int answer = firstValue + secondValue;
// 足したint型の数字を,
// Stringクラスの静的関数valueOfに入れるとString型として出力してくれる
textField.setText(String.valueOf(answer));
}
else if(actionCommand.equals("sub_two_values")){
// 引き算の場合も,処理は足し算と同じ
String givenString = textField.getText();
System.out.println(givenString);
String[] givenValues = givenString.split(",", -1);
int firstValue = Integer.parseInt(givenValues[0]);
int secondValue = Integer.parseInt(givenValues[1]);
int answer = firstValue - secondValue;
textField.setText(String.valueOf(answer));
}
}
} //インナークラスここまで
}