Java8 の「ラムダ式」・「関数インターフェース」あたりを試すついでに NetBeans の環境設定方法とかもメモする。
#環境
##OS
Windows7 64bit
##Java
1.8.0-ea-b118
##NetBeans
7.4(Java8 に対応してるのは 7.4 から)
#準備
##NetBeans のインストール
NetBeans IDE ダウンロード ここから NetBeans のインストーラをダウンロードする。
ダウンロードした exe を実行して、インストーラに従ってインストール。
##JDK8 のインストール
JDK8 Early Access Releases Project Kenai ここから exe をダウンロード。
ダウンロードした exe を実行して、インストーラに従ってインストール。
#NetBeans のセットアップ
##カラースキームの変更
エディタの色は重要です。少なくとも、デフォルトの白背景は発狂しそうになるので暗い色に変更する。
ここに色々なカラースキームが上げられている。
この中で、 Avanzzzi v3 か Icarus あたりが個人的には良さげだった。
zip をダウンロードしたら、以下の手順で NetBeans に適用する。
- [ツール] → [オプション] → [フォントと色] → [インポート] をクリック
- ダウンロードしていた zip ファイルを選択
- [使用可能なオプション] で [すべて] にチェックを入れて [OK] をクリック
NetBeans が再起動したら、カラーテーマが適用される。
##空白文字の表示
デフォルトだと空白文字が表示されず発狂しそうになる。
なので、見えるようにする。
[表示] → [表示不可能な文字を表示] を選択してチェックを入れる。
##フォントの変更
デフォルトの英字フォントは見づらくて発狂しそうになるので Consolas に切り替える。
しかし、 Consolas は日本語文字に対応してないので、単純にフォントを Consolas に変えただけだと日本語が表示できなくなってしまう。
なので、 Java のフォント設定を変更し、 Monospaced を選択したら英字フォントが Consolas で、日本語フォントは MS ゴシックで表示されるようにする。
以下のサイトが参考になりました。
# monospaced のフォント設定部分
monospaced.plain.alphabetic=Courier New
monospaced.bold.alphabetic=Courier New Bold
monospaced.italic.alphabetic=Courier New Italic
monospaced.bolditalic.alphabetic=Courier New Bold Italic
# フォントの優先順序設定部分
sequence.monospaced.windows-31j=japanese,alphabetic,dingbats,symbol
# monospaced のフォント設定部分
monospaced.plain.alphabetic=Consolas
monospaced.bold.alphabetic=Consolas Bold
monospaced.italic.alphabetic=Consolas Italic
monospaced.bolditalic.alphabetic=Consolas Bold Italic
# フォントの優先順序設定部分
sequence.monospaced.windows-31j=alphabetic,japanese,dingbats,symbol
# Consolas の設定追記
filename.Consolas=CONSOLA.TTF
filename.Consolas_Bold=CONSOLAB.TTF
filename.Consolas_Italic=CONSOLAI.TTF
filename.Consolas_Bold_Italic=CONSOLAZ.TTF
#NetBeans のショートカットとか
Eclipse でよく使っている機能が、 NetBeans ではどうすればいいのかをまとめる。
##基本操作
ショートカット・操作 | 機能 | Eclipse の場合 |
---|---|---|
Ctrl + e |
選択行削除 | Ctrl + d |
Ctrl + Shift + c |
選択行コメントアウト | 同じ |
Ctrl + Space |
入力補完 | 同じ |
Ctrl + Shift + i |
インポート文の修正 | Ctrl + Shift + o |
Ctrl + クリック |
クリックしたメソッド(クラス)に移動 | 同じ |
Ctrl + Shift + テンキーの - |
全コードブロックの縮小 | Ctrl + Shift + テンキーの / |
Ctrl + Shift + テンキーの + |
全コードブロックの展開 | Ctrl + Shift + テンキーの * |
Ctrl + w |
現在開いているエディタを閉じる | 同じ |
F6 |
プロジェクトを実行 | Ctrl + F11 |
Ctrl + F5 |
プロジェクトをデバッグ実行 | F11 |
Shift + F11 |
クリーンアップしてからビルド | デフォルトは無し? |
Ctrl + r |
リファクタリング | Shfit + Alt + r |
##デバッグ中の操作
ショートカット・操作 | 機能 | Eclipse の場合 |
---|---|---|
F8 |
ステップ・オーバー | F6 |
F7 |
ステップ・イン | F5 |
F5 |
再開 | F8 |
##テンプレート
キーワード | 生成されるコード | Eclipse の場合 |
---|---|---|
sout |
System.out.println("") |
sysout |
#NetBeans で Java8 を使えるようにする
##Java プラットフォームに Java8 を追加する
[ツール] → [Javaプラットフォーム] を選択。
[Java プラットフォーム・マネージャ] が開くので、 [プラットフォームの追加] を選択。
先ほどインストールしておいた Java8 の JDK フォルダを選択して [次へ] → [終了]。
##プロジェクトで使用する JDK を Java8 にする
プロジェクトを右クリックして、 [プロパティ] を選択。
[ライブラリ] の [Java プラットフォーム] で先ほど追加した [JDK1.8] を選択する。
[ソース] の [ソース/バイナリ形式] で [JDK8] を選択する。
これで Java8 でのプログラミングができるようになる。
#ラムダ式を試す
##基本
package java8sample;
public class Java8Sample {
public static void main(String[] args) {
MyInterface lambda = str -> "Hello " + str + " !!";
System.out.println(lambda.method("Lambda"));
}
private static interface MyInterface {
String method(String str);
}
}
Hello Lamda !!
- 抽象メソッドを1つだけ持つインターフェースには、ラムダ式を代入できる。
- ラムダ式は、
(引数) -> 処理;
と記述する。 -
引数
が1つの場合は( )
を省略できる。 - ラムダ式が単一行の場合は、
処理
を評価した結果が return される。 -
引数
には型を記述することもできるが、省略しても型推論してくれる。
##引数なし
package java8sample;
public class Java8Sample {
public static void main(String[] args) {
MyInterface lambda = () -> "引数なし";
System.out.println(lambda.method());
}
private static interface MyInterface {
String method();
}
}
-
()
は省略できない。
##引数が複数
package java8sample;
public class Java8Sample {
public static void main(String[] args) {
MyInterface lambda = (i, str) -> String.format("i=%d, str=%s", i, str);
System.out.println(lambda.method(10, "string"));
}
private static interface MyInterface {
String method(int i, String str);
}
}
i=10, str=string
##複数行のラムダ式
package java8sample;
public class Java8Sample {
public static void main(String[] args) {
MyInterface lambda = i -> {
if (i % 2 == 0) {
return "偶数";
} else {
return "奇数";
}
};
System.out.println(lambda.method(11));
}
private static interface MyInterface {
String method(int i);
}
}
奇数
- ラムダ式内が複数行に渡る場合は
{ }
で処理
を括る。 - 複数行の場合は
return
が必須になる(戻り値がvoid
なら不要)。
##ラムダ式の外の変数は final でなくても参照できる
package java8sample;
public class Java8Sample {
public static void main(String[] args) {
String str = "not final";
MyInterface lambda = () -> System.out.println(str);
lambda.method();
}
private static interface MyInterface {
void method();
}
}
not final
- ラムダ式の外で宣言されている変数は、
final
宣言されていなくても参照できる。
##でも外部の変数は事実上のfinalじゃないとコンパイルエラー
package java8sample;
public class Java8Sample {
public static void main(String[] args) {
String str = "not final";
MyInterface lambda = () -> {
str = "上書き不可"; // コンパイルエラーになる
System.out.println(str);
};
lambda.method();
}
private static interface MyInterface {
void method();
}
}
- ラムダ式外で宣言されていて、ラムダ式内で参照されている変数は 事実上のfinal である必要がある。
-
str
はラムダ式外で宣言されており、かつラムダ式内で参照されているので、変更しようとするとコンパイルエラーになる。
##ラムダ式外での書き換えも当然不可
package java8sample;
public class Java8Sample {
public static void main(String[] args) {
String str = "not final";
MyInterface lambda = () -> System.out.println(str);
lambda.method();
str = "上書き不可"; // コンパイルエラー
}
private static interface MyInterface {
void method();
}
}
#関数インターフェース
抽象メソッドが1つしか存在しないインターフェースのことを 関数インターフェース と呼ぶ。
関数インターフェースには、ラムダ式が代入できる。
##@FunctionalInterface
アノテーションで関数インターフェースを定義する
package java8sample;
@FunctionalInterface
public interface MyInterface {
void method();
}
Java8 で追加された @FunctionalInterface
アノテーションをインターフェースに付与すると、そのインターフェースは 関数インターフェース とみなされる。
@FunctionalInterface
アノテーションをインターフェースに付与すると、そのインターフェースはメソッドを1つしか宣言できなくなり、複数のメソッドを宣言するとコンパイルエラーになる。
つまり、そのインターフェースにはラムダ式が必ず代入できる、ということをコンパイルレベルで保証できる。
##java.util.function
パッケージには、よく使いそうな関数インターフェースが定義されている
java.util.function
パッケージには、関数インターフェースがたくさん定義されている。
基本はここで定義されている関数インターフェースを利用して、どうしても自分のニーズに合わない場合は独自で関数インターフェースを定義する。 と思う。たぶん。
#関数オブジェクト
##クラスメソッドを関数オブジェクトとして取得する
package java8sample;
public class Java8Sample {
public static void main(String[] args) {
MyInterface func = Java8Sample::staticMethod;
func.method();
}
public static void staticMethod() {
System.out.println("Java8Sample#staticMethod()");
}
@FunctionalInterface
private static interface MyInterface {
void method();
}
}
Java8Sample#staticMethod()
-
<クラス名>::<クラスメソッド名>
で、そのクラスのメソッドを関数オブジェクトとして取得できる。
##取得しようとしているメソッドがオーバーロードされている場合は、代入先の関数インターフェースに合わせて取得できるメソッドが切り換わる
package java8sample;
public class Java8Sample {
public static void main(String[] args) {
NoneArgument none = Java8Sample::staticMethod;
none.method();
SingleArgument single = Java8Sample::staticMethod;
single.method("hoge");
}
public static void staticMethod() {
System.out.println("Java8Sample#staticMethod()");
}
public static void staticMethod(String str) {
System.out.printf("Java8Sample#staticMethod(%s)%n", str);
}
@FunctionalInterface
private static interface NoneArgument {
void method();
}
@FunctionalInterface
private static interface SingleArgument {
void method(String str);
}
}
Java8Sample#staticMethod()
Java8Sample#staticMethod(hoge)
- メソッドの参照はどちらも
Java8Sample::staticMethod
となっているが、取得された関数オブジェクトは代入先の関数インターフェースに合わせて切り替わっている。
##インスタンスメソッドを関数オブジェクトとして取得する
package java8sample;
public class Java8Sample {
public static void main(String[] args) {
Java8Sample sample = new Java8Sample("Hoge");
MyInterface func = sample::instanceMethod;
func.method();
}
private String name;
public Java8Sample(String name) {
this.name = name;
}
public void instanceMethod() {
System.out.println("My name is " + this.name);
}
@FunctionalInterface
private static interface MyInterface {
void method();
}
}
My name is Hoge
-
<インスタンス>::<インスタンスメソッド名>
で、そのインスタンスのメソッドを取得できる。
##実行時のインスタンスを指定できるインスタンスメソッドを取得する
package java8sample;
public class Java8Sample {
public static void main(String[] args) {
MyInterface func = Java8Sample::instanceMethod;
Java8Sample sample = new Java8Sample("Hoge");
func.method(sample, "hoge");
}
private String name;
public Java8Sample(String name) {
this.name = name;
}
public void instanceMethod(String str) {
System.out.println("My name is " + this.name + ". str=" + str);
}
@FunctionalInterface
private static interface MyInterface {
void method(Java8Sample instance, String str);
}
}
My name is Hoge. str=hoge
-
<クラス名>::<インスタンスメソッド名>
で実行時のインスタンスを指定できるインスタンスメソッドが取得できる。 - 関数インターフェース側は、第一引数に実行時のインスタンスが渡せるようにシグニチャを定義する。
- インスタンスメソッドへの引数は、第二引数以降に渡す。
#インターフェースにデフォルト実装が定義できるようになった
package java8sample;
public class Java8Sample {
public static void main(String[] args) {
new MyClass().method();
}
private static class MyClass implements MyInterface {
}
private static interface MyInterface {
default void method() {
System.out.println("default method");
}
}
}
default method
-
default
をメソッド定義の前につければ、インターフェースでも実装を記述することができる。
##つまり、多重継承が可能になった
package java8sample;
public class Java8Sample {
public static void main(String[] args) {
MyClass myClass = new MyClass();
myClass.hoge();
myClass.fuga();
}
private static class MyClass implements Hoge, Fuga {
}
private static interface Hoge {
default void hoge() {
System.out.println("hoge");
}
}
private static interface Fuga {
default void fuga() {
System.out.println("fuga");
}
}
}
hoge
fuga
- インターフェースは複数実装可能なので、事実上多重継承が可能になった
##同じシグネチャのデフォルトメソッドを持つインターフェースを複数実装した場合、実装クラスでオーバーライドしなければならない
package java8sample;
public class Java8Sample {
public static void main(String[] args) {
MyClass myClass = new MyClass();
myClass.method();
}
private static class MyClass implements Hoge, Fuga { // コンパイルエラー
}
private static interface Hoge {
default void method() {
System.out.println("hoge");
}
}
private static interface Fuga {
default void method() {
System.out.println("fuga");
}
}
}
↓オーバーライド
package java8sample;
public class Java8Sample {
public static void main(String[] args) {
MyClass myClass = new MyClass();
myClass.method();
}
private static class MyClass implements Hoge, Fuga {
@Override
public void method() {
System.out.println("MyClass");
}
}
private static interface Hoge {
default void method() {
System.out.println("hoge");
}
}
private static interface Fuga {
default void method() {
System.out.println("fuga");
}
}
}
MyClass
#参考
- NetBeansカラースキーム6個まとめ|プログラム|Nullyのぶろぐ
- NetBeansでConsolasフォントを使う - unoh.github.com by unoh
- NetBeans 6.9 開発版を試す:空白やタブを表示する (Masaki Katakai's Weblog)
- NetBeans IDE キーボードショートカット
- 祝 Java8 Project Lambda リリース!につき、ラムダ式コトハジメ - 倭マンs BLOG
- java.util.function パッケージ - 倭マンs BLOG
- Java8新機能 ラムダ式とデフォルトメソッドの導入理由 - Yuji Blog
- Java8で最もインパクトのある構文拡張、デフォルトメソッド - きしだのはてな