そもそもメソッド参照とは
ラムダ式の書き方をするときに条件に合う場合に出来る見やすい書き方。
メソッドの動作をあるメソッドからそのまま譲渡するような場合に、いちいち矢印(->)を書かなくて良くなるのと、どのメソッドを参照しているか一目で分かり易くなる。
自分は主にStreamでよく使う。
複数のボタンでそれぞれ別の動作を設定したい時にswitch文で分岐せずとも、以下の様に使い分けられる。
今までの書き方
public class Main implements ActionListener {
Main(){
button1.addActionListener(this);
button2.addActionListener(this);
button3.addActionListener(this);
}
@Override
public void actionPerformed(ActionEvent e){
switch(e.getActionCommand()){
/* 分岐条件とそれぞれの動作 */
}
}
}
メソッド参照を使った書き方
public class Main {
Main(){
button1.addActionListener(this::btn1Action);
button2.addActionListener(this::btn2Action);
button3.addActionListener(this::btn3Action);
}
private void btn1Action(ActionEvent e){
/* さまざまな処理 */
}
private void btn2Action(ActionEvent e){
/* さまざまな処理 */
}
private void btn3Action(ActionEvent e){
/* さまざまな処理 */
}
}
ActionListenerを実装せずとも書ける!
またメソッド名や可視性も自由に指定できる!
Javaのメソッド参照の書き方には大きく分けて4種ある
- 変数名::メソッド名
- this::メソッド名
- クラス名::new
- クラス名::staticメソッド名
- クラス名::インスタンスメソッド名
- static変数名::staticメソッド名
以下のコードを元に説明する。
public class MyFrame extends JFrame {
private JPanel rootPanel = new JPanel(new FlowLayout());
private JButton btn = new JButton("ok");
private JLabel label = new JLabel("none");
private Set<JChechBox> set = new HashSet<>();
public static void main(String[] args){
SwingUtilites.invokeLater(() -> new MyFrame().setVisible(true))
}
public MyFrame(){
Stream.of("strbery", "banana", "kiwi", "apple", "pineapple")
.map(this::change)// 2. this::メソッド名
.map(JCheckBox::new)// 3. クラス名::new
.forEach(c -> {
panel.add(c);
set.add(c);
});
panel.add(label);
add(btn, BorderLayout.SOUTH);
btn.addActionListener(this::perform);// 2.this::メソッド名
}
private String change(String s){
// 文字の長さと文字を半角スペースで繋いで返す。(例「abc」を「3 abc」に。)
return s.length() + " " + s;
}
private void perform(ActionEvent e){
String text = set.stream()
.filter(JCheckBox::isSelected)// 5. クラス名::インスタンスメソッド名
.map(JCheckBox::getText)// 5. クラス名::インスタンスメソッド名
.peek(System.out::println)// 6. static変数名::staticメソッド名
.reduce((r, v) -> r + "[" + v + "]")
.orElse("null")
label.setText(text);
}
}
変数名::メソッド名
あるインスタンスのメソッドを使うときの書き方。
this::メソッド名
メソッド参照を書いているクラス自身のメソッドを使うときの書き方。
クラス名::new
引数を元にクラス名のインスタンスを生成する。
クラス名::staticメソッド名
普通にstaticメソッドを使うのと同様に書く。
クラス名::インスタンスメソッド名
主にStream内で使うときの書き方。
Stream内を通るそれぞれの要素のメソッドを使うとき、その要素のクラス名と使うメソッド名をコロン2つで結ぶ。
上記のコードでは、Set内の各要素のisSelectedメソッドを呼び出す為に、クラス名を用いて使うメソッドを特定している。
set.stream().filter(JChechBox::isSelected)
動作:setの要素それぞれに対して、JChechBoxクラスのisSelectedメソッドを呼び出して、選択状態のチェックボックスのみにしている。
static変数名::staticメソッド名
set.forEach(System.out::println)
などでよく使う。
動作:Systemクラスのstatic変数であるoutの、printlnメソッドを呼び出している。