内部クラスとラムダ式の勉強メモ

苦手な内部クラスとラムダ式の勉強メモです。。

# 内部クラス

## クラスの中に、クラスが作れる

```java
//外部クラス
class Outer{
    //内部クラス
    class Inner{
        //
    }
}
```

## クラスのメソッドの中に、クラスが作れる
メソッドの中に定義した内部クラスの生成は、このメソッド内でしか、出来ない。

```java
class Outer{
    void test() {
        class Inner{
        }
        Inner in = new Inner();
    }
}

```

内部クラスは、外部クラスのprivateなインスタンス変数にアクセスできる。

```java
class Outer{
    private String msg = "hoge";

    void test() {
        class Inner{
            void test() {
                System.out.println(msg);
            }
        }
        Inner in = new Inner();
        in.test();
    }
}

public class MultiThreadEx {
    public static void main(String[] args) {
        Outer o = new Outer();
        o.test();
    }
}

```

# 匿名クラス（AnonymousClass）
内部クラスの仲間。クラス名がないものを匿名クラスという。

準備：

```java
interface Hello{
    public void hello();
}
class Greeting {
    static void greet(Hello s) {
        s.hello();
    }
}
````

一般的な例：

```java
class Person implements Hello{
    @Override
    public void hello() {
        // TODO 自動生成されたメソッド・スタブ
        System.out.println("はよ");
    }
}
public class SampleProgram{
    public static void main(String[] args)  {
        Person p = new Person();
        Greeting.greet(p);

    }
}
```

内部クラスの例：

```java
//内部クラスの書き方
public class SampleProgram{
    public static void main(String[] args) {
        class Person implements Hello{

            @Override
            public void hello() {
                // TODO 自動生成されたメソッド・スタブ
                System.out.println("はに");
            }
        }
        Person p = new Person();
        Greeting.greet(p);
        //上記2行を1行にした書き方
        Greeting.greet(new Person());
    }
}
```

匿名クラスの例：
メソッドの引数を指定する場所で、クラス宣言を行うと、クラス名を付ける必要がなくなる。
うーん、、、慣れないなぁ。。。

```java
public class SampleProgram{
    public static void main(String[] args) {
        Greeting.greet(new Hello() {

            @Override
            public void hello() {
                // TODO 自動生成されたメソッド・スタブ
                System.out.println("ねむい");

            }
        });
    }
}

```

# ラムダ式

関数型インターフェースを実装したクラスの宣言を、ラムダ式のルール？に従って
コードを省略する書き方（？）

```java
(引数列) -> {処理内容}
```

## 関数型インターフェースとは
抽象メソッドを１つしか持たないインターフェースのこと。
2つ以上のメソッドがあるとダメらしい。

試しに、メソッドを追加したら

```
The target type of this expression must be a functional interface
//この式のターゲット型は、関数インタフェースでなければなりません
型 Greeting のメソッド greet(Hello) は引数 (() -> {}) に適用できません
```

とコンパイルエラーが表示された。

## 匿名クラスで作成した処理をラムダ式に書き換えると

```java
public class SampleProgram{
    public static void main(String[] args) {
        Greeting.greet( () -> { System.out.println("おなかすいた"); } );
    }
}
```

## ルール

- 引数列の型は省略できる
- 引数が1つだけの場合は、引数を囲む () を省略できる
- 処理の中身に命令文が１つだけの場合、処理を囲む {} とreturenキーワード、セミコロン(;)を省略できる


```java
//修正前：
Greeting.greet( () -> { System.out.println("おなかすいた"); } );

//修正後：
Greeting.greet( () -> System.out.println("おなかすいた"));
```

## ラムダ式を使ってループ文を作ろう

```java
import java.util.ArrayList;
import java.util.List;

class Animal{
    private String type ;
    private String name;

    Animal(String t, String n){
        this.type = t;
        this.name = n;
    }

    public void showAnimal() {
        System.out.println(this.type+":"+this.name);;
    }
}

public class SampleProgram{
    public static void main(String[] args) {
        List<Animal> list = new ArrayList<Animal>();

        list.add(new Animal("ねこ","たま"));
        list.add(new Animal("インコ", "ピーコ"));
        list.add(new Animal("いぬ","ぽち"));

        //ラムダ式
        list.forEach((Animal a) ->{ a.showAnimal();});
        //ラムダ式の省略形
        list.forEach(a -> a.showAnimal());
    }
}
```