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中的元素轉成大寫,倒序,並輸出。
//看看這種做法,和以前要實現這種做法的區別。現在這種做法是不是太好了。
}
}
歡迎大家多討論,交流。祝同學們學業有成。