匿名類
- 當接口、抽象類的實現類,在整個項目中只用過一次,可以考慮使用匿名類
- 定義一個接口或抽象類
public interface Eatable { String name(); int energy(); }
- 在main方法中,直接new一個這個接口的匿名類
打印結果public static void main(String[] args) { // TODO Auto-generated method stub String string = "你是:"; Eatable eatable = new Eatable() { @Override public String name() { // TODO Auto-generated method stub return string + "君無殤"; } @Override public int energy() { // TODO Auto-generated method stub return 100; } }; System.out.println(eatable.name() + ",能量值:" + eatable.energy()); }
你是:君無殤,能量值:100
- 匿名類不能定義除編譯時常量以外的任何static成員
- 匿名類只能訪問final或者有效final的局部變量
- 匿名類可以直接訪問外部類中的所有成員(即使被聲明為private)
匿名類只有在實例相關的代碼塊中使用,才能直接訪問外部類中的實例成員(實例變量、實例方法) - 匿名類不能自定義構造方法、但可以有初始化塊
匿名類的常見用途
- 代碼傳遞
- 定義一個Times類,并添加一個test靜態方法,再在這個類中定義一個抽象類Block
public class Times { abstract class Block{ abstract void execute(); } public static void test(Block block) { long begin = System.currentTimeMillis(); block.execute(); long end = System.currentTimeMillis(); double duration = (end - begin) / 1000.0; System.out.println("耗時:" + duration + "秒"); } }
- 在main方法中調用test方法,并申明一個匿名類
打印結果為:public static void main(String[] args) { // TODO Auto-generated method stub Times.test(new Times().new Block() { int add = 0; @Override void execute() { // TODO Auto-generated method stub int number = 100000000; for (int i = 0; i < number; i++) { add++; } } }); }
耗時:0.007秒
- 過濾器
例如Arrays.sort的排序,默認是升序排列public static void main(String[] args) { // TODO Auto-generated method stub Integer[] nums = {1, 4, 6, 2, 8, 3, 9, 7, 5}; //數據源:[1, 4, 6, 2, 8, 3, 9, 7, 5] System.out.println("數據源:" + Arrays.toString(nums)); //升序 Arrays.sort(nums); //升序:[1, 2, 3, 4, 5, 6, 7, 8, 9] System.out.println("升序:" + Arrays.toString(nums)); //降序 Arrays.sort(nums, new Comparator<Integer>() {//匿名類 @Override public int compare(Integer o1, Integer o2) { // TODO Auto-generated method stub return o2 - o1; } }); //降序:[9, 8, 7, 6, 5, 4, 3, 2, 1] System.out.println("降序:" + Arrays.toString(nums)); }
- 回調
比如進行網絡數據請求時,請求數據的返回等問題。
Lambda(函數式接口)
- 函數式接口(Function Interface):只包含1個抽象方法的接口
可以在接口上面加上@FunctionInterface注解,便是它是一個函數式接口 - 只能訪問final或者有效final的局部變量
- 沒有引入新的作用域
public class Times { @FunctionalInterface public interface Block{ void execute(); } public static void test(Block block) { long begin = System.currentTimeMillis(); block.execute(); long end = System.currentTimeMillis(); double duration = (end - begin) / 1000.0; System.out.println("耗時:" + duration + "秒"); } }
打印結果public static void main(String[] args) { // TODO Auto-generated method stub Times.test(() -> { int num = 1000000000; for (int i = 0; i < num; i++) { } }); }
耗時:0.001秒
方法引用
如果Lambda中的內容僅僅是調用某個方法,可以使用方法引用(Method Reference)來簡化
-
引用類方法
- 創建函數接口
@FunctionalInterface public interface Testable { int test(int v1, int v2); }
- 使用Lambda表達式
Testable t1 = (v1, v2) -> Math.max(v1, v2); System.out.println(t1.test(30, 40));
- 使用方法引用
Testable t2 = Math::max; System.out.println(t2.test(30, 40));
-
引用特定對象的實例方法
- 創建函數接口,對象和在Main文件中靜態方法
@FunctionalInterface public interface Testable { void test(int v1); }
public class Person { public void setAge(int age) { System.out.println("Person - setAge -" + age); } }
static void execute(Testable t, int v) { t.test(v); }
- 使用Lambda表達式
execute(v -> System.out.println(v), 10); execute(v -> new Person().setAge(v), 10);
- 使用方法引用
execute(System.out::println, 10); execute(new Person()::setAge, 10);
-
引用特定類型的任意對象的實例方法
- 創建一個字符串數組
String[] strings = { "Jack", "james", "Apple", "abort" };
- 使用Lambda表達式
Arrays.parallelSort(strings, (s1, s2) -> s1.compareToIgnoreCase(s2));
- 使用方法引用
Arrays.parallelSort(strings, String::compareToIgnoreCase);
-
引用構造方法
- 創建函數接口,包含有構造方法的對象
@FunctionalInterface public interface Testable { Object test(int v1); }
public class Person { public Person(int age) { System.out.println("Person -" + age); } }
- 使用Lambda表達式
Testable t1 = v -> new Person(v); System.out.println(t1.test(18));
- 使用方法引用
Testable t1 = Person::new; System.out.println(t1.test(18));
-
引用當前類中定義的實例方法
- 創建函數接口,對象
@FunctionalInterface public interface Testable { void test(int v1); }
public class Person { public void setAge(int age) { System.out.println("Person - setAge -" + age); } }
- 使用Lambda表達式
public void show() { Testable t1 = v -> setAge(v); t1.test(10); }
- 使用方法引用
Testable t1 = this::setAge; t1.test(10);
-
引用父類中定義的實例方法
- 創建函數接口,對象和這個對象的子類
@FunctionalInterface public interface Testable { void test(int v1); }
public class Person { public void setAge(int age) { System.out.println("Person - setAge - " + age); } }
public class Student extends Person { public void setAge(int age) { System.out.println("Student - setAge - " + age); } }
- 使用Lambda表達式
Testable t1 = v -> super.setAge(v); t1.test(10);
- 使用方法引用
Testable t2 = super::setAge; t2.test(10);