Android 使用Java8新特性之"方法引用"
2017-03-13 18:10
691 查看
前言
上一文:Android 使用Java8新特性之Lambda expression (附命令者模式简化)说过lambda表达式,在android studio中的环境配置及应用。本文讲下Java8新特性之”方法引用”。
“方法引用”,它其实可以看成lambda表达式的一种简写形式。
再回顾一下lambda表达式的应用场景:简化仅含单一抽象方法接口的调用
方法引用的4种形式
方法引用的符号形式,形如,[className | class-instance]::[static-method | instance-method | construct-method]
即,以类名或类的实例对象为前缀,中间以两个冒号(::)连接,后跟静态方法 或 实例方法 或 构造方法
分类:
1. 静态方法引用
2. 实例方法引用
3. 类实例方法引用
4. 构造方法引用
静态方法引用
类MethodReferenceActivity下有一静态方法:static int parz(String str) {//被lambda表达式或"方法引用"调用 return Integer.parseInt(str); }
如果直接调用 MethodReferenceActivity::parz当然是不行的,因为”方法引用”是用来替换lambda表达式的,所以也将指代一个仅含单一抽象方法的接口。
再有一个接口:
public interface ToIntFunc<T> {//注:原生jdk中就有的方法,安卓中没有 int applyAsInt(T value); }
再有一个使用ToIntFunc接口的静态方法:
public static int parse(ToIntFunc<String> f, String num) { return f.applyAsInt(num); }
调用parse()时使用lambda表达式:
int parseValue = parse((value -> parz(value)), num);
调用parse()时使用”方法引用”:
int parseValue = parse(MethodReferenceActivity::parz, num);
实例方法引用
将上面的方法parse方法声明中的static 去掉:public int parse(ToIntFunc<String> f, String num) { return f.applyAsInt(num); }
调用parse()时使用”方法引用”:
int parseValue = parse(this::parz, num); //this指当前类的实例对象
类实例方法引用
需要在外部调用方法中,声明参数
如有一个内部类Person:static class Person { public Person() { } public Person(String name) { this.name = name; } String name; Long birthday; public Long getBirthday() { return birthday; } public String getName() { return name; } public boolean compareByName(Person b) { int result = this.name.compareToIgnoreCase(b.name); if (result == 1) { return true; } else { return false; } } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", birthday=" + birthday + '}'; } public void printInfo() { System.out.println(toString()); } }
有一个接口Compare:
public interface Compare<T> { boolean compareTo(T v1, T v2); }
外部的使用接口Compare的调用方法isLarge:
public boolean isLarge(Compare<Person> c, Person p1, Person p2) { return c.compareTo(p1, p2); }
使用lambda表达式和类实例方法引用:
Person p1 = new Person("stone"); Person p2 = new Person("sun"); boolean result = isLarge((v1, v2) -> v1.compareByName(v2), p1, p2); System.out.println("p1 排序在 p2 后: " + result); result = isLarge(Person::compareByName, p1, p2); System.out.println("p1 排序在 p2 后: " + result);
这里isLarge方法,除接口外,还要求传递两个Person的实例对象。这两个对象,被Compare接口中的compareTo方法使用。
不需要在外部调用方法中,声明参数
再来看如下一组代码:Integer[] ary = {2, 8, 1, 5, 6, 3, 4}; Arrays.sort(ary, (o1, o2) -> o1.compareTo(o2)); Arrays.sort(ary, Integer::compareTo);
这是调用数组工具类Arrays.sort()来进行排序。
在【Arrays.sort(ary, Integer::compareTo);】中,”类实例方法引用”实际指代java.util.Comparator接口,接口中的静态方法为:int compare(T o1, T o2);而这里并没有传递o1、o2参数。o1,o2的实例化,实际上是在sort方法内部完成的。 就好比如下示例,
/**内部实例化*/ public boolean isLarge(Compare<Person> c) { Person p1 = new Person("stone"); Person p2 = new Person("austin"); return c.compareTo(p1, p2); }
使用lambda和类实例方法引用:
isLarge((v1, v2) -> v1.compareByName(v2));//lambda expression isLarge(Person::compareByName);//method reference
构造方法引用
现有下面的代码:static class Person { String name; public Person() { } public Person(String name) { this.name = name; } } public interface GetType<T> { T get(String value); } public interface GetType2<T> { T get(); } public Person getPerson(String name, GetType<Person> data) { return data.get(name); } public Person getPerson(GetType2<Person> data) { return data.get(); }
使用lambda和构造方法引用:
getPerson("li si", value -> new Person(value));//lambda //会调用new Person(String name) 指代GetType getPerson("zhang san", Person::new); getPerson(() -> new Person());//lambda getPerson(Person::new);//会调用new Person() 指代GetType2
总结
不管是lambda表达式,还是”方法引用”,它们都指代一个仅含单一抽象方法接口的匿名内部类实例。使用”方法引用”后,一看表达式,就能猜出方法引用的类别。同时配合AS,看调用方法的接口。“方法引用”表达式的返回值与接口中方法的返回值一致。”方法引用”表达式所调用方法的参数,可以通过外部调用方法来传值。如果有参数,而没传值,可能在外部方法内部进行了初始化,如”类实例方法引用”第二个示例。
lambda表达式,是可以有一个方法体的。现在有了”方法引用”,就不用看起来那么”混乱”了。比如:
button.setOnTouchListener((view, event)-> { if (event.getAction() == MotionEvent.ACTION_DOWN) { //do sth. return true; } else if (event.getAction() == MotionEvent.ACTION_MOVE) { //do sth. return true; } return super.onTouchEvent(event); });
只需要声明一个方法:
private boolean handleEvent(View v, MotionEvent event) { //do sth. return true; }
如下使用”方法引用”调用:
button.setOnTouchListener(this::handleEvent);
相关文章推荐
- 2011/06/13 android使用html做UI的方法---js与java的相互调用
- [Android] "Failed to find Java version for 'C:\Windows\system32\java.exe"问题的解决方法
- Android程序 依赖库引用Gson 报java.lang.NoClassDefFoundError: com/google/gson/Gson 解决方法
- Android "java.lang.NoClassDefFoundError:*"报错的处理方法
- "Invalid file name: must contain only [a-z0-9_.]"android项目中R.java文件丢失原因及解决方法.
- 生成动态库so的方法|解决NDK r5b引用静态库失效的问题|在NDK的Nactive代码中使用Android Log的方法|生成Native java头文件
- 引用天下会"使用OleDbCommandBuilder时出现“Insert into 语句的语法错误”的解决方法"
- java android split() 方法 split("||") split("|") 需要转义 为 split("\\|")
- java使用Iterator迭代出现"java.uitl.ConcurrentModificationException"错误原因及解决方法概述
- android基础笔记:数据库SQLite应用2(使用java方法)
- Android中split,java.util.StringTokenizer和indexOf的使用以及各方法效率的对比
- android学习笔记---53_采用网页设计软件界面,以及使用android系统内置的浏览器,利用js调用java方法
- 关于Android使用HttpClient中出现的"java.lang.NoClassDefFoundError"
- Android使用百度地图SDK调用百度地图"java.lang.UnsatisfiedLinkError: Native method not found: com.baidu.platform."
- 第一课 掌握java annotation特性与使用方法
- Java中软引用、弱引用和虚引用的使用方法示例
- 使用Eclipse开发Android出现java.lang.NullPointerException错误的解决方法
- Java中Soap的几种使用方法(android 可用)
- android4.0 禁止横竖屏切换使用 android:configChanges="orientation|keyboardHidden"无效的解决方法
- 2011/06/13 android使用html做UI的方法---js与java的相互调用