Edited at

Java8のラムダ式とかを試すついでにNetBeansの環境設定方法とかもメモ

More than 5 years have passed since last update.

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 v3Icarus あたりが個人的には良さげだった。

zip をダウンロードしたら、以下の手順で NetBeans に適用する。


  • [ツール] → [オプション] → [フォントと色] → [インポート] をクリック

  • ダウンロードしていた zip ファイルを選択

  • [使用可能なオプション] で [すべて] にチェックを入れて [OK] をクリック

NetBeans が再起動したら、カラーテーマが適用される。


空白文字の表示

デフォルトだと空白文字が表示されず発狂しそうになる。

なので、見えるようにする。

[表示] → [表示不可能な文字を表示] を選択してチェックを入れる。


フォントの変更

デフォルトの英字フォントは見づらくて発狂しそうになるので Consolas に切り替える。

しかし、 Consolas は日本語文字に対応してないので、単純にフォントを Consolas に変えただけだと日本語が表示できなくなってしまう。

なので、 Java のフォント設定を変更し、 Monospaced を選択したら英字フォントが Consolas で、日本語フォントは MS ゴシックで表示されるようにする。

以下のサイトが参考になりました。


fontconfig.properties(変更前)

# 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



fontconfig.properties(変更後)

# 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 でなくても参照できる


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じゃないとコンパイルエラー


ラムダ式内で参照されている変数は事実上の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 パッケージには、関数インターフェースがたくさん定義されている。

基本はここで定義されている関数インターフェースを利用して、どうしても自分のニーズに合わない場合は独自で関数インターフェースを定義する。  と思う。たぶん。


関数オブジェクト


クラスメソッドを関数オブジェクトとして取得する


staticメソッドを関数オブジェクトとして取得する

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



参考