# Anonymous Class
https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html
前面我們寫過一些interface, abstract class, 並且有個子類別繼承他們,
但是每次我們要建立一種介面實作, 或是抽象類別的子類, 就要建立一個class, 有時候只是希望一次性使用, 就會很麻煩。
所以我們可以不直接寫子類別, 直接new 一個interface/abstract class,
並且要實作方法。
寫法: ```new InterfaceOrAbstractClass(constructor param) {declaration};```
Example:
下面範例有三種, Printer class, IPrinter interface, PrinterAbstract abstract class
並且寫了個別的實作方式。
```java
class Printer {
public void print(String s) {
System.out.println(s);
}
}
interface IPrinter {
void print(String s);
}
class PrinterAbstract {
public abstract void print(String s);
}
// ---------- in Main.java ----------
public class Main {
public static void main(String[] args) {
Printer v = new Printer() {
@Override
public void print(String s) {
System.out.print("Class : " + s);
}
};
v3.print("Hello"); // Class : Hello
IPrinter v2 = new IPrinter() {
@Override
public void print(String s) {
System.out.print("Interface : " + s);
}
};
v3.print("Hello"); // Interface : Hello
PrinterAbstract v3 = new PrinterAbstract() {
@Override
public void print(String s) {
System.out.print("Abstract Class : " + s);
}
};
v3.print("Hello"); // Abstract Class : Hello
}
}
```
總之class, abstract class, interface寫法都一樣。
# Lambda
https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
如果Interface 的non-static方法只有一個
我們可以把傳統的Interface Anoymous Class改寫成:
`(param) -> statement`
```java=
interface MathFunction {
void run(int x,int y);
}
public class Main {
public static void main(String[] args) {
// 原本寫法
MathFunction sum = new MathFunction() {
@Override
public void run(int x, int y) {
System.out.println(x + y);
}
};
sum.run(10, 20); // 30
MathFunction multiply = (x, y) -> {
int result = x * y;
System.out.println(result);
};
multiply.run(10, 20); // 200
MathFunction subtract = (x, y) -> System.out.println(x - y);
subtract.run(20, 10); // 10
}
}
```
---
如果param只有一個的話可以省去小括號
```java=
interface MathFunction {
void run(int x);
}
public class Main {
public static void main(String[] args) {
MathFunction pow = x -> System.out.println(x * x);
pow.run(10,20); //200
}
}
```
<br>
### Lambda with return value
如果lambda有return值:
有幾種寫法:
```
(param) -> <return value>
```
```
(param) -> {
...
return xxx;
}
```
```java=
interface MathFunction {
int run(int x,int y);
}
public class Main {
public static void main(String[] args) {
MathFunction sum = new MathFunction() {
@Override
public int run(int x,int y) {
return x + y;
}
};
System.out.println(sum.run(10,20))); //30
MathFunction multiply = (x,y) -> {
int result = x * y;
return result;
};
System.out.println(multiply.run(10,20)); //200
//x * y is the return value itself.
MathFunction subtract = (x,y) -> x - y;
System.out.println(subtract.run(20, 10)); // 10
}
}
```
### Method Reference
https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
- static method
`ClassName::staticMethodName`
- non-static method
`object::instanceMethodName`
- constructor
`ClassName::new`
如果Lambda的效果如同呼叫一個方法/建構子, 可以用該方法的Method Reference代替。
```java
class Methods {
public static int sum(int x, int y) {
return x + y;
}
}
class Test {
public void sum(int x, int y) {
return x + y;
}
}
```
---
像是這個加法
```java
(x, y) -> x + y;
```
- 可以寫成
```java
(x, y) -> Methods.sum(x, y)
Method::sum
```
- 如果是非靜態方法, 可以寫成
```java
Test obj = // ...
(x, y) -> obj.sum(x, y)
obj::sum
```
---
如果是呼叫建構子
```java
(x, y) -> new Point(x, y);
```
可以寫成
```java
Point::new
```
---
哪邊會用到這鬼東西?
最常見的應該是foreach,在許多Collections都會用到
```java=
List<String> list = new ArrayList<>();
list.add("hello1");
list.add("hello2");
list.add("hello3");
for(String s : list)
System.out.println(s);
list.forEach(s -> System.out.println(s));
list.forEach(System.out::println);
```