Java8简明教程
Java  /  管理员 发布于 4年前   544
Java 8已于2014年3月18日正式发布了,新版本带来了诸多改进,包括Lambda表达式、Streams、日期时间API等等。本文就带你领略Java 8的全新特性。
一.允许在接口中有默认方法实现
Java 8 允许我们使用default关键字,为接口声明添加非抽象的方法实现。这个特性又被称为扩展方法。下面是我们的第一个例子:
package com.bijian.study;interface Formula { double calculate(int a); default double sqrt(int a) { return Math.sqrt(a); }}
在接口Formula中,除了抽象方法caculate以外,还定义了一个默认方法sqrt。Formula的实现类只需要实现抽象方法caculate就可以了。默认方法sqrt可以直接使用。
package com.bijian.study;public class FormulaTest {public static void main(String[] args) {Formula formula = new Formula() { @Override public double calculate(int a) { return sqrt(a * 100); }}; double calRes = formula.calculate(100); // 100.0System.out.println(calRes);double sqRes = formula.sqrt(16); // 4.0System.out.println(sqRes);}}
formula对象以匿名对象的形式实现了Formula接口。代码很啰嗦:用了6行代码才实现了一个简单的计算功能:a*100开平方根。我们在下一节会看到,Java 8 还有一种更加优美的方法,能够实现包含单个函数的对象。
二.Lambda表达式
让我们从最简单的例子开始,来学习如何对一个string列表进行排序。我们首先使用Java 8之前的方法来实现:
package com.bijian.study;import java.util.Arrays;import java.util.Collections;import java.util.Comparator;import java.util.List;public class Lambda {public static void main(String[] args) {List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");Collections.sort(names, new Comparator<String>() {@Overridepublic int compare(String a, String b) {return b.compareTo(a);}});System.out.println(names);//[xenia, peter, mike, anna]}}
静态工具方法Collections.sort接受一个list,和一个Comparator接口作为输入参数,Comparator的实现类可以对输入的list中的元素进行比较。通常情况下,你可以直接用创建匿名Comparator对象,并把它作为参数传递给sort方法。
除了创建匿名对象以外,Java 8 还提供了一种更简洁的方式,Lambda表达式。
package com.bijian.study;import java.util.Arrays;import java.util.Collections;import java.util.List;public class LambdaTest {public static void main(String[] args) { List<String> names = Arrays.asList("peter", "anna", "mike", "xenia"); Collections.sort(names, (String a, String b) -> { return b.compareTo(a); }); System.out.println(names);//[xenia, peter, mike, anna] }}
你可以看到,这段代码就比之前的更加简短和易读。但是,它还可以更加简短:
package com.bijian.study;import java.util.Arrays;import java.util.Collections;import java.util.List;public class LambdaTest {public static void main(String[] args) { List<String> names = Arrays.asList("peter", "anna", "mike", "xenia"); Collections.sort(names, (String a, String b) -> b.compareTo(a)); System.out.println(names);//[xenia, peter, mike, anna] }}
只要一行代码,包含了方法体。你甚至可以连大括号对{}和return关键字都省略不要。不过这还不是最短的写法:
package com.bijian.study;import java.util.Arrays;import java.util.Collections;import java.util.List;public class LambdaTest {public static void main(String[] args) { List<String> names = Arrays.asList("peter", "anna", "mike", "xenia"); Collections.sort(names, (a, b) -> b.compareTo(a)); System.out.println(names);//[xenia, peter, mike, anna] }}
Java编译器能够自动识别参数的类型,所以你就可以省略掉类型不写。让我们再深入地研究一下lambda表达式的威力吧。
三.函数式接口
Lambda表达式如何匹配Java的类型系统?每一个lambda都能够通过一个特定的接口,与一个给定的类型进行匹配。一个所谓的函数式接口必须要有且仅有一个抽象方法声明。每个与之对应的lambda表达式必须要与抽象方法的声明相匹配。由于默认方法不是抽象的,因此你可以在你的函数式接口里任意添加默认方法。
任意只包含一个抽象方法的接口,我们都可以用来做成lambda表达式。为了让你定义的接口满足要求,你应当在接口前加上@FunctionalInterface
标注。编译器会注意到这个标注,如果你的接口中定义了第二个抽象方法的话,编译器会抛出异常。
举例:
package com.bijian.study;@FunctionalInterface public interface Converter <F, T> { T convert(F from); default double add100(int a) { return a + 100; } default double mul3(double a) { return a*3; }}
package com.bijian.study;public class ConverterImpl {public static void main(String[] args) {Converter<String, Integer> converter = (from) -> Integer.valueOf(from); Integer converted = converter.convert("123"); System.out.println(converted); // 123System.out.println(converter.mul3(converter.add100(converted)));//669.0}}
注意,如果你不写@FunctionalInterface 标注,程序也是正确的。
四.方法与构造函数引用
上面的代码实例可以通过静态方法引用,使之更加简洁:
package com.bijian.study;public class ConverterImpl {public static void main(String[] args) {Converter<String, Integer> converter = Integer::valueOf;Integer converted = converter.convert("123");System.out.println(converted); // 123}}
Java 8 允许你通过::关键字获取方法或者构造函数的的引用。上面的例子就演示了如何引用一个静态方法。而且,我们还可以对一个对象的方法进行引用:
package com.bijian.study;public class Something {String startsWith(String s) { return String.valueOf(s.charAt(0)); }public static void main(String[] args) {Something something = new Something();Converter<String, String> converter = something::startsWith;String converted = converter.convert("Java");System.out.println(converted); // "J"}}
让我们看看如何使用::关键字引用构造函数。首先我们定义一个示例bean,包含不同的构造方法:
package com.bijian.study;class Person { String firstName; String lastName; Person() {} Person(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public String toString() { return this.firstName + " " + this.lastName; } public static void main(String[] args) { PersonFactory<Person> personFactory = Person::new; Person person = personFactory.create("Peter", "Parker"); System.out.println(person); }}
接下来,我们定义一个person工厂接口,用来创建新的person对象:
package com.bijian.study;interface PersonFactory<P extends Person> { P create(String firstName, String lastName);}
然后我们通过构造函数引用来把所有东西拼到一起,而不是像以前一样,通过手动实现一个工厂来这么做,如上Person类中的main方法。
PersonFactory<Person> personFactory = Person::new;Person person = personFactory.create("Peter", "Parker");
我们通过Person::new来创建一个Person类构造函数的引用。Java编译器会自动地选择合适的构造函数来匹配PersonFactory.create函数的签名,并选择正确的构造函数形式。
123 在
Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..原梓番博客 在
在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..博主 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..1111 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..路人 在
php中使用hyperf框架调用讯飞星火大模型实现国内版chatgpt功能示例中评论 教程很详细,如果加个前端chatgpt对话页面就完美了..Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号