Java 8全面解析
函數式接口
函數式接口是只定義了一個抽象方法的接口。Java 8引入了FunctionalInterface注解來表明一個接口打算成為一個函數式接口。例如,java.lang.Runnable就是一個函數式接口。
<pre>@FunctionalInterface public interface Runnable { public abstract void run(); }</pre>注意,不管FunctionalInterface注解是否存在,Java編譯器都會將所有滿足該定義的接口看作是函數式接口.....
</div>
改進接口
現在可以在接口中定義靜態方法了。例如,java.util.Comparator接口中現在擁有一個靜態的naturalOrder方法。
public static <T extends Comparable<? super T>> Comparator <T>naturalOrder() { return (Comparator<T>) Cmparators.NaturalOrderComparator.INSTANCE; }
還能夠在接口中提供默認方法。通過該功能,程序員能夠在不破壞已有的接口實現代碼的前提下添加新方法。例如,java.lang.Iterable接口現在擁有一個默認的forEach方法。
public default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } }
注意,接口不能為Object類中的任何方法提供默認的實現....
Lambda
函數式接口的重要屬性是:我們能夠使用lambda實例化它們,Lambda表達式讓你能夠將函數作為方法參數,或者將代碼作為數據對待。下面是Lambda的一些例子。輸入在左邊,代碼在右邊。輸入類型能夠被推斷出來,同時是可選的.............
(int x, int y) ->{ return x + y; } (x, y) -> x + y x -> x * x () -> x x -> { System.out.println(x); }
下面是實例化Runnable函數式接口的一個例子.............
Runnable r = () ->{ System.out.println("Running!"); }
方法引用
方法引用是簡潔的Lambda表達式,能夠用于已經擁有名稱的方法。下面是一些方法引用的例子,右邊是同樣效果的Lambda表達式。
String::valueOf x ->String.valueOf(x) Object::toString x ->x.toString() x::toString () ->x.toString() ArrayList::new () -> new ArrayList<>()
與捕獲相對的非捕獲Lambda
如果使用Lambda表達式訪問一個在Lambda語句體外定義的非靜態變量或者對象,那么它會被說成是“捕獲”。例如,下面的Lambda會訪問變量x:
int x = 5; return y -> x + y;
一個Lambda表達式僅能夠訪問final或者有效final封閉塊中的局部變量和參數...............
java.util.function
新版本向 java.util.function包中添加了很多新的函數式接口。下面是一些例子:
- Function<T, R>——將T作為輸入,返回R作為輸出
- Predicate<T>——將T作為輸入,返回一個布爾值作為輸出
- Consumer<T>——將T作為輸入,不返回任何內容
- Supplier<T>——沒有輸入,返回T
- BinaryOperator<T>——將兩個T作為輸入,返回一個T作為輸出 </ul>
java.util.stream
新的 java.util.stream包提供了對值流進行函數式操作的類。從一個集合中獲取流的一種常見方式是:
Stream<T> stream = collection.stream();
下面是一個來自于Javadocs包中的例子..........
intsumOfWeights = blocks.stream().filter(b ->b.getColor() == RED) .mapToInt(b ->b.getWeight()) .sum();
在該例子中我們首先使用了一個塊集合作為流的來源,然后在流上執行了filter-map-reduce操作獲取紅塊重量的和。
流可以是無限的、有狀態的,可以是順序的,也可以是并行的。在使用流的時候,你首先需要從一些來源中獲取一個流,執行一個或者多個中間操作,然后執行一個最終操作。中間操作包括filter、map、flatMap、peel、distinct、sorted、limit和substream。終止操作包括forEach、toArray、reduce、collect、min、max、count、anyMatch、allMatch、 noneMatch、findFirst和findAny。 java.util.stream.Collectors是一個非常有用的實用類。該類實現了很多歸約操作,例如將流轉換成集合和聚合元素............
改進了泛型推斷
這提升了Java編譯器推斷泛型和在泛型方法調用中減少顯式類型參數的能力。在Java 7中,代碼如下:
foo(Utility.<Type>bar()); Utility.<Type>foo().bar();
在Java 8中,改進后的參數和調用鏈推斷讓你能夠按照下面的方式編寫代碼:
foo(Utility.bar()); Utility.foo().bar();
java.time
新的日期/時間API包含在 java.time包中。所有的類都是不可變且線程安全的。日期和時間類型包括Instant、LocalDate、LocalTime、 LocalDateTime和ZonedDateTime。除了日期和時間之外,還有Duration和Period類型。另外,值類型包括Month、 DayOfWeek、Year、 Month、YearMonth、MonthDay、OffsetTime和OffsetDateTime。這些新的日期/時間類大部分JDBC都支持。
新增集合API
接口可以擁有默認函數的能力讓Java 8得以向集合API中添加大量的新方法。所有的接口都提供了默認的實現,而更加有效的實現則是被添加到了具體的類中。下面是新方法的列表:
- Iterable.forEach(Consumer)
- Iterator.forEachRemaining(Consumer)
- Collection.removeIf(Predicate)
- Collection.spliterator()
- Collection.stream()
- Collection.parallelStream()
- List.sort(Comparator)
- List.replaceAll(UnaryOperator)
- Map.forEach(BiConsumer)
- Map.replaceAll(BiFunction)
- Map.putIfAbsent(K, V)
- Map.remove(Object, Object)
- Map.replace(K, V, V)
- Map.replace(K, V)
- Map.computeIfAbsent(K, Function)
- Map.computeIfPresent(K, BiFunction)
- Map.compute(K, BiFunction)
- Map.merge(K, V, BiFunction)
- Map.getOrDefault(Object, V) </ul>
- BufferedReader.lines()
- Files.list(Path)
- Files.walk(Path, int, FileVisitOption...)
- Files.walk(Path, FileVisitOption...)
- Files.find(Path, int, BiPredicate, FileVisitOption...)
- Files.lines(Path, Charset)
- DirectoryStream.stream() </ul>
新增并發API
Java 8還向并發API中添加了一些新內容,我們將會在此簡要介紹其中的一部分。ForkJoinPool.commonPool()是處理所有并行流操作的結構。沒有明確提交到某個特定池中的所有ForkJoinTask都將會使用通用池。ConcurrentHashMap已經被完全重寫。 StampedLock是一個新的鎖實現,它可以作為ReentrantReadWriteLock的一個備選方案。CompletableFuture 是Future接口的一個實現,它為異步任務的執行和鏈接提供了方法.......
新增IO/NIO API
在Java 8中有一些新的IO/NIO方法,我們能夠使用它們從文件或者輸入流中獲取java.util.stream.Stream。
這里面有一個新的UncheckedIOException,它是一個繼承了RuntimetimeException的IOException。還有一個CloseableStream,它是一個能夠并且應該被關閉的流...........
反射和注解的變化
通過類型注解,我們能夠在更多的地方使用注解,例如像List<@Nullable String>這樣的泛型參數中。這增強了通過靜態分析工具發現錯誤的能力,它將增強并重定義Java內置的類型系統...........
Nashorn JavaScript引擎
Nashorn是一個集成到JDK中的新的、輕量級、高性能的JavaScript實現。Nashorn是Rhino的繼任者,它提升了性能和內存使用情況。它將會支持javax.script API,但是它并不會支持DOM/CSS,也不會包含瀏覽器插件API........