匿名类
- 当接口、抽象类的实现类,在整个项目中只用过一次,可以考虑使用匿名类
- 定义一个接口或抽象类
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);