Java 8或许是迄今为止最令人期待的Java版本,最初定于2013年的9月份发布,
但由于一系列的安全漏洞问题,最终在2014年的3月18日才发布了正式版。
作为同门兄弟,NetBeans 8.0跟JDK 8同时发布,在版本号上也与JDK保持一致。
看来,关键时刻还得靠兄弟啊。呵呵。
下载链接:
那么,在经过这么长的时间闭关修炼后,Java 8到底为我们带来了什么呢?
从官方的一些介绍中,大致的有如下的新特性:
1:允许在接口中有默认方法实现
2:Lambda表达式
3:函数式接口
4:内置函数式接口
5:Streams和
6:Map
7:时间日期API
8:Annotations
如果有同学或者朋友在自己的新项目中使用到Java 8,如果有新的发现,或者问题,
可以在我们论坛提出问题交流。共同推进Java语言的发展和进步。
下面我仅仅就其中几个比较有意思的写个代码简单测试一下。
1:允许在接口中有默认方法实现
可以使用default关键字和static关键字修饰方法并给出方法体。
代码如下:
/*
Java 8 允许我们使用default关键字,为接口声明添加非抽象的方法实现。
这个特性又被称为扩展方法。除此以外,Java 8还允许为接口声明添加静态的方法实现,
但是,在使用的时候只能通过接口名称去限定使用。
*/
//接口
interface Inter
{
//抽象方法
public abstract void show();
//default方法
public default void defaultPrint()
{
System.out.println("defaultPrint 我爱林青霞");
}
//static方法
public static void staticPrint()
{
System.out.println("staticPrint 我爱林青霞");
}
}
//实现类
class InterImpl implements Inter
{
public void show()
{
System.out.println("重写接口中的方法");
}
}
//测试类
public class Demo01
{
public static void main(String[] args)
{
Inter i = new InterImpl();
i.show();
i.defaultPrint();
//如下使用是错误的
//i.staticPrint();
//错误: 静态接口方法调用非法,应将接收方表达式替换为类型限定符 'Inter'
//正确用法
Inter.staticPrint();
}
}
2:Lambda表达式
"Lambda 表达式"(lambda expression)是一个匿名函数,即没有函数名的函数。
Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。
代码如下:
import java.util.List;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
/*
需求:对多个字符串进行排序。
我将分别采用Java 8之前的解决方案和Java 8之后的解决方案,大家自己看那个好。
*/
public class Demo02
{
public static void main(String[] args)
{
String[] strArray = {"hello","world","java"};
//调用Java 8之前的解决方案
stringSort(strArray);
//遍历数组
for(String str : strArray)
{
System.out.println(str);
}
System.out.println("-----------------------");
//调用Java 8之后的解决方案
stringSort2(strArray);
//遍历数组
for(String str : strArray)
{
System.out.println(str);
}
}
//Java 8之前的解决方案。
public static void stringSort(String[] strArray)
{
//把字符串数组转成集合
List<String> list = Arrays.asList(strArray);
//使用集合工具类的排序功能
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s1.compareTo(s2);
}
});
}
//Java 8之后的解决方案,Lambda表达式(如果不知道是什么,自己先google下)
public static void stringSort2(String[] strArray)
{
//把字符串数组转成集合
List<String> list = Arrays.asList(strArray);
//使用集合工具类的排序功能,采用Lambda表达式实现
//Collections.sort(list, (String s1, String s2) -> {
//return s1.compareTo(s2);
//});
//通过上面的代码,你可以发现它比我们以前的方式要简洁。
//但是,它还可以更简洁
//只要一行代码,包含了方法体。你甚至可以连大括号对{}和return关键字都省略不要。
//Collections.sort(list, (String s1, String s2) -> s1.compareTo(s2));
//但是这还不是最简洁的,最终版代码如下:
Collections.sort(list, (s1, s2) -> s1.compareTo(s2));
//Java编译器能够自动识别参数的类型,所以你就可以省略掉类型不写。
}
}
3:函数式接口和内置函数式接口
代码如下:
/*
函数式接口:
Lambda表达式是如何匹配Java中的类型的呢?
每一个lambda都能够通过一个特定的接口,与一个给定的类型进行匹配。
一个所谓的函数式接口必须要有且仅有一个抽象方法声明。
每个与之对应的lambda表达式必须要与抽象方法的声明相匹配。
由于默认方法不是抽象的,因此你可以在你的函数式接口里任意添加默认方法。
内置函数式接口:
JDK 1.8 API中包含了很多内置的函数式接口。有些是在以前版本的Java中大家耳熟能详的,
例如Comparator接口,或者Runnable接口。对这些现成的接口进行实现,
可以通过@FunctionalInterface 标注来启用Lambda功能支持。
Comparator接口在Java 7时候的源码 :
package java.util;
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
}
Comparator接口在Java 8时候的源码:
package java.util;
import java.io.Serializable;
import java.util.function.Function;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.function.ToDoubleFunction;
import java.util.Comparators;
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
default Comparator<T> reversed() {
return Collections.reverseOrder(this);
}
default Comparator<T> thenComparing(Comparator<? super T> other) {
Objects.requireNonNull(other);
return (Comparator<T> & Serializable) (c1, c2) -> {
int res = compare(c1, c2);
return (res != 0) ? res : other.compare(c1, c2);
};
}
default <U> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
return thenComparing(comparing(keyExtractor, keyComparator));
}
default <U extends Comparable<? super U>> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor)
{
return thenComparing(comparing(keyExtractor));
}
default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor) {
return thenComparing(comparingInt(keyExtractor));
}
default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor) {
return thenComparing(comparingLong(keyExtractor));
}
default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor) {
return thenComparing(comparingDouble(keyExtractor));
}
public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
return Collections.reverseOrder();
}
@SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;
}
public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) {
return new Comparators.NullComparator<>(true, comparator);
}
public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) {
return new Comparators.NullComparator<>(false, comparator);
}
public static <T, U> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
Objects.requireNonNull(keyExtractor);
Objects.requireNonNull(keyComparator);
return (Comparator<T> & Serializable)
(c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
keyExtractor.apply(c2));
}
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor)
{
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}
public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
}
public static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2));
}
public static<T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2));
}
}
此外,Java 8 API 还提供了很多新的函数式接口,来降低程序员的工作负担。
下面我们通过一个案例来学习Java 8内置的函数式接口的使用。
*/
import java.util.ArrayList;
import java.util.List;
public class Demo03
{
public static void main(String[] args)
{
//创建集合对象
List<String> list = new ArrayList<String>();
//添加元素
list.add("hello");
list.add("world");
list.add("java");
list.add("itcast");
list.add("javase");
list.add("javaee");
list.add("android");
//filter接受一个predicate接口类型的变量,并将所有流对象中的元素进行过滤。
//list.stream().filter((s) -> s.startsWith("j")).forEach(System.out::println);
//sorted是一个中间操作,能够返回一个排过序的流对象的视图。
//流对象中的元素会默认按照自然顺序进行排序,
//除非你自己指定一个Comparator接口来改变排序规则。
//list.stream().sorted().filter((s) -> s.startsWith("j")).forEach(System.out::println);
//map是一个对于流对象的中间操作,通过给定的方法,
//它能够把流对象中的每一个元素对应到另外一个对象上。
list.stream().map(String::toUpperCase).sorted((a, b) -> b.compareTo(a)).forEach(System.out::println);
//基本思路就是:把list中的元素转成大写,倒序,并输出。
//看看这种做法,和以前要实现这种做法的区别。现在这种做法是不是太好了。
}
}
欢迎大家多讨论,交流。祝同学们学业有成。