东莞一站式网站推广运营,dw做aspx网站,产品推广语,行业网站产品选择Java8 中文指南#xff08;一#xff09; 文章目录 Java8 中文指南#xff08;一#xff09;《Java8 指南》中文翻译接口的默认方法(Default Methods for Interfaces)Lambda 表达式(Lambda expressions)函数式接口(Functional Interfaces)方法和构造函数引用(Method and Co…Java8 中文指南一 文章目录 Java8 中文指南一《Java8 指南》中文翻译接口的默认方法(Default Methods for Interfaces)Lambda 表达式(Lambda expressions)函数式接口(Functional Interfaces)方法和构造函数引用(Method and Constructor References)Lambda 表达式作用域(Lambda Scopes)访问局部变量访问字段和静态变量访问默认接口方法 《Java8 指南》中文翻译
随着 Java 8 的普及度越来越高很多人都提到面试中关于 Java 8 也是非常常问的知识点。应各位要求和需要我打算对这部分知识做一个总结。本来准备自己总结的后面看到 GitHub 上有一个相关的仓库地址 https://github.com/winterbe/java8-tutorial。这个仓库是英文的我对其进行了翻译并添加和修改了部分内容下面是正文。 欢迎阅读我对 Java 8 的介绍。本教程将逐步指导您完成所有新语言功能。 在简短的代码示例的基础上您将学习如何使用默认接口方法lambda 表达式方法引用和可重复注释。 在本文的最后您将熟悉最新的 API 更改如流函数式接口(Functional Interfaces)Map 类的扩展和新的 Date API。 没有大段枯燥的文字只有一堆注释的代码片段。
接口的默认方法(Default Methods for Interfaces)
Java 8 使我们能够通过使用 default 关键字向接口添加非抽象方法实现。 此功能也称为虚拟扩展方法。
第一个例子
interface Formula{double calculate(int a);default double sqrt(int a) {return Math.sqrt(a);}}Formula 接口中除了抽象方法计算接口公式还定义了默认方法 sqrt。 实现该接口的类只需要实现抽象方法 calculate。 默认方法sqrt 可以直接使用。当然你也可以直接通过接口创建对象然后实现接口中的默认方法就可以了我们通过代码演示一下这种方式。
public class Main {public static void main(String[] args) {// 通过匿名内部类方式访问接口Formula formula new Formula() {Overridepublic double calculate(int a) {return sqrt(a * 100);}};System.out.println(formula.calculate(100)); // 100.0System.out.println(formula.sqrt(16)); // 4.0}}formula 是作为匿名对象实现的。该代码非常容易理解6 行代码实现了计算 sqrt(a * 100)。在下一节中我们将会看到在 Java 8 中实现单个方法对象有一种更好更方便的方法。
译者注 不管是抽象类还是接口都可以通过匿名内部类的方式访问。不能通过抽象类或者接口直接创建对象。对于上面通过匿名内部类方式访问接口我们可以这样理解一个内部类实现了接口里的抽象方法并且返回一个内部类对象之后我们让接口的引用来指向这个对象。
Lambda 表达式(Lambda expressions)
首先看看在老版本的 Java 中是如何排列字符串的
ListString names Arrays.asList(peter, anna, mike, xenia);Collections.sort(names, new ComparatorString() {Overridepublic int compare(String a, String b) {return b.compareTo(a);}
});只需要给静态方法Collections.sort 传入一个 List 对象以及一个比较器来按指定顺序排列。通常做法都是创建一个匿名的比较器对象然后将其传递给 sort 方法。
在 Java 8 中你就没必要使用这种传统的匿名对象的方式了Java 8 提供了更简洁的语法lambda 表达式
Collections.sort(names, (String a, String b) - {return b.compareTo(a);
});可以看出代码变得更短且更具有可读性但是实际上还可以写得更短
Collections.sort(names, (String a, String b) - b.compareTo(a));对于函数体只有一行代码的你可以去掉大括号{}以及 return 关键字但是你还可以写得更短点
names.sort((a, b) - b.compareTo(a));List 类本身就有一个 sort 方法。并且 Java 编译器可以自动推导出参数类型所以你可以不用再写一次类型。接下来我们看看 lambda 表达式还有什么其他用法。
函数式接口(Functional Interfaces)
译者注 原文对这部分解释不太清楚故做了修改
Java 语言设计者们投入了大量精力来思考如何使现有的函数友好地支持 Lambda。最终采取的方法是增加函数式接口的概念。“函数式接口”是指仅仅只包含一个抽象方法,但是可以有多个非抽象方法(也就是上面提到的默认方法)的接口。 像这样的接口可以被隐式转换为 lambda 表达式。java.lang.Runnable 与 java.util.concurrent.Callable 是函数式接口最典型的两个例子。Java 8 增加了一种特殊的注解FunctionalInterface,但是这个注解通常不是必须的(某些情况建议使用)只要接口只包含一个抽象方法虚拟机会自动判断该接口为函数式接口。一般建议在接口上使用FunctionalInterface 注解进行声明这样的话编译器如果发现你标注了这个注解的接口有多于一个抽象方法的时候会报错的如下图所示 示例
FunctionalInterface
public interface ConverterF, T {T convert(F from);
}// TODO 将数字字符串转换为整数类型ConverterString, Integer converter (from) - Integer.valueOf(from);Integer converted converter.convert(123);System.out.println(converted.getClass()); //class java.lang.Integer译者注 大部分函数式接口都不用我们自己写Java8 都给我们实现好了这些接口都在 java.util.function 包里。
方法和构造函数引用(Method and Constructor References)
前一节中的代码还可以通过静态方法引用来表示 ConverterString, Integer converter Integer::valueOf;Integer converted converter.convert(123);System.out.println(converted.getClass()); //class java.lang.IntegerJava 8 允许您通过::关键字传递方法或构造函数的引用。 上面的示例显示了如何引用静态方法。 但我们也可以引用对象方法
class Something {String startsWith(String s) {return String.valueOf(s.charAt(0));}
}Something something new Something();
ConverterString, String converter something::startsWith;
String converted converter.convert(Java);
System.out.println(converted); // J接下来看看构造函数是如何使用::关键字来引用的首先我们定义一个包含多个构造函数的简单类
class Person {String firstName;String lastName;Person() {}Person(String firstName, String lastName) {this.firstName firstName;this.lastName lastName;}
}接下来我们指定一个用来创建 Person 对象的对象工厂接口
interface PersonFactoryP extends Person {P create(String firstName, String lastName);
}这里我们使用构造函数引用来将他们关联起来而不是手动实现一个完整的工厂
PersonFactoryPerson personFactory Person::new;
Person person personFactory.create(Peter, Parker);我们只需要使用 Person::new 来获取 Person 类构造函数的引用Java 编译器会自动根据PersonFactory.create方法的参数类型来选择合适的构造函数。
Lambda 表达式作用域(Lambda Scopes)
访问局部变量
我们可以直接在 lambda 表达式中访问外部的局部变量
final int num 1;
ConverterInteger, String stringConverter (from) - String.valueOf(from num);stringConverter.convert(2); // 3但是和匿名对象不同的是这里的变量 num 可以不用声明为 final该代码同样正确
int num 1;
ConverterInteger, String stringConverter (from) - String.valueOf(from num);stringConverter.convert(2); // 3不过这里的 num 必须不可被后面的代码修改即隐性的具有 final 的语义例如下面的就无法编译
int num 1;
ConverterInteger, String stringConverter (from) - String.valueOf(from num);
num 3;//在lambda表达式中试图修改num同样是不允许的。访问字段和静态变量
与局部变量相比我们在 lambda 表达式中对实例字段和静态变量都有读写访问权限。 该行为和匿名对象是一致的。
class Lambda4 {static int outerStaticNum;int outerNum;void testScopes() {ConverterInteger, String stringConverter1 (from) - {outerNum 23;return String.valueOf(from);};ConverterInteger, String stringConverter2 (from) - {outerStaticNum 72;return String.valueOf(from);};}
}访问默认接口方法
还记得第一节中的 formula 示例吗 Formula 接口定义了一个默认方法sqrt可以从包含匿名对象的每个 formula 实例访问该方法。 这不适用于 lambda 表达式。
无法从 lambda 表达式中访问默认方法,故以下代码无法编译
Formula formula (a) - sqrt(a * 100);大家好我是xwhking一名技术爱好者目前正在全力学习 Java前端也会一点如果你有任何疑问请你评论或者可以加我QQ2837468248说明来意希望能够与你共同进步