jdk7和jdk8的一些新特性及區別
在jdk7的新特性方面主要有下面幾方面的增強:
1
.jdk7語法上
1.1
二進位制變數的表示,支援將整數型別用二進位制來表示,用0b開頭。
// 所有整數 int, short,long,byte都可以用二進位制表示
// An 8-bit 'byte' value:
byte
aByte = (
byte
) 0b00100001;
// A 16-bit 'short' value:
short
aShort = (
short
) 0b1010000101000101;
// Some 32-bit 'int' values:
intanInt1 = 0b10100001010001011010000101000101;
intanInt2 = 0b101;
intanInt3 = 0B101;
// The B can be upper or lower case.
// A 64-bit 'long' value. Note the "L" suffix:
long
aLong = 0b1010000101000101101000010100010110100001010001011010000101000101L;
// 二進位制在陣列等的使用
final
int
[] phases = { 0b00110001, 0b01100010, 0b11000100, 0b10001001,
0b00010011, 0b00100110, 0b01001100, 0b10011000 };
1.2
Switch語句支援string型別
public
static
String getTypeOfDayWithSwitchStatement(String dayOfWeekArg) {
String typeOfDay;
switch
(dayOfWeekArg) {
case
"Monday"
:
typeOfDay =
"Start of work week"
;
break
;
case
"Tuesday"
:
case
"Wednesday"
:
case
"Thursday"
:
typeOfDay =
"Midweek"
;
break
;
case
"Friday"
:
typeOfDay =
"End of work week"
;
break
;
case
"Saturday"
:
case
"Sunday"
:
typeOfDay =
"Weekend"
;
break
;
default
:
throw
new
IllegalArgumentException(
"Invalid day of the week: "
+ dayOfWeekArg);
}
return
typeOfDay;
}
1.3
Try-with-resource語句
注意:實現java.lang.AutoCloseable介面的資源都可以放到
try
中,跟
final
裡面的關閉資源類似; 按照宣告逆序關閉資源 ;Try塊丟擲的異常通過Throwable.getSuppressed獲取
try
(java.util.zip.ZipFile zf =
new
java.util.zip.ZipFile(zipFileName);
java.io.BufferedWriter writer = java.nio.file.Files
.newBufferedWriter(outputFilePath, charset)) {
// Enumerate each entry
for
(java.util.Enumeration entries = zf.entries(); entries
.hasMoreElements();) {
// Get the entry name and write it to the output file
String newLine = System.getProperty(
"line.separator"
);
String zipEntryName = ((java.util.zip.ZipEntry) entries
.nextElement()).getName() + newLine;
writer.write(zipEntryName,
0
, zipEntryName.length());
}
}
1.4
Catch多個異常 說明:Catch異常型別為
final
; 生成Bytecode 會比多個
catch
小; Rethrow時保持異常型別
public
static
void
main(String[] args)
throws
Exception {
try
{
testthrows();
}
catch
(IOException | SQLException ex) {
throw
ex;
}
}
public
static
void
testthrows()
throws
IOException, SQLException {
}
1.5
數字型別的下劃線表示 更友好的表示方式,不過要注意下劃線新增的一些標準,可以參考下面的示例
long
creditCardNumber = 1234_5678_9012_3456L;
long
socialSecurityNumber = 999_99_9999L;
float
pi =
3
.14_15F;
long
hexBytes = 0xFF_EC_DE_5E;
long
hexWords = 0xCAFE_BABE;
long
maxLong = 0x7fff_ffff_ffff_ffffL;
byte
nybbles = 0b0010_0101;
long
bytes = 0b11010010_01101001_10010100_10010010;
//float pi1 = 3_.1415F; // Invalid; cannot put underscores adjacent to a decimal point
//float pi2 = 3._1415F; // Invalid; cannot put underscores adjacent to a decimal point
//long socialSecurityNumber1= 999_99_9999_L; // Invalid; cannot put underscores prior to an L suffix
//int x1 = _52; // This is an identifier, not a numeric literal
int
x2 = 5_2;
// OK (decimal literal)
//int x3 = 52_; // Invalid; cannot put underscores at the end of a literal
int
x4 = 5_______2;
// OK (decimal literal)
//int x5 = 0_x52; // Invalid; cannot put underscores in the 0x radix prefix
//int x6 = 0x_52; // Invalid; cannot put underscores at the beginning of a number
int
x7 = 0x5_2;
// OK (hexadecimal literal)
//int x8 = 0x52_; // Invalid; cannot put underscores at the end of a number
int
x9 = 0_52;
// OK (octal literal)
int
x10 = 05_2;
// OK (octal literal)
//int x11 = 052_; // Invalid; cannot put underscores at the end of a number
1.6
泛型例項的建立可以通過型別推斷來簡化 可以去掉後面
new
部分的泛型型別,只用<>就可以了。
//使用泛型前
List strList =
new
ArrayList();
List<String> strList4 =
new
ArrayList<String>();
List<Map<String, List<String>>> strList5 =
new
ArrayList<Map<String, List<String>>>();
//編譯器使用尖括號 (<>) 推斷型別
List<String> strList0 =
new
ArrayList<String>();
List<Map<String, List<String>>> strList1 =
new
ArrayList<Map<String, List<String>>>();
List<String> strList2 =
new
ArrayList<>();
List<Map<String, List<String>>> strList3 =
new
ArrayList<>();
List<String> list =
new
ArrayList<>();
list.add(
"A"
);
// The following statement should fail since addAll expects
// Collection<? extends String>
//list.addAll(new ArrayList<>());
1.7
在可變引數方法中傳遞非具體化引數,改進編譯警告和錯誤
Heap pollution 指一個變數被指向另外一個不是相同型別的變數。例如
List l =
new
ArrayList<Number>();
List<String> ls = l;
// unchecked warning
l.add(
0
,
new
Integer(
42
));
// another unchecked warning
String s = ls.get(
0
);
// ClassCastException is thrown
Jdk7:
public
static
<T>
void
addToList (List<T> listArg, T... elements) {
for
(T x : elements) {
listArg.add(x);
}
}
你會得到一個warning
warning: [varargs] Possible heap pollution from parameterized vararg type
要消除警告,可以有三種方式
1
.加 annotation
@SafeVarargs
2
.加 annotation
@SuppressWarnings
({
"unchecked"
,
"varargs"
})
3
.使用編譯器引數 –Xlint:varargs;
1.8
資訊更豐富的回溯追蹤 就是上面
try
中
try
語句和裡面的語句同時丟擲異常時,異常棧的資訊
java.io.IOException
§? at Suppress.write(Suppress.java:
19
)
§? at Suppress.main(Suppress.java:
8
)
§? Suppressed: java.io.IOException
§? at Suppress.close(Suppress.java:
24
)
§? at Suppress.main(Suppress.java:
9
)
§? Suppressed: java.io.IOException
§? at Suppress.close(Suppress.java:
24
)
§? at Suppress.main(Suppress.java:
9
)
2
. NIO2的一些新特性
1
.java.nio.file 和java.nio.file.attribute包 支援更詳細屬性,比如許可權,所有者
2
. symbolic and hard links支援
3
. Path訪問檔案系統,Files支援各種檔案操作
4
.高效的訪問metadata資訊
5
.遞迴查詢檔案樹,檔案擴充套件搜尋
6
.檔案系統修改通知機制
7
.File類操作API相容
8
.檔案隨機訪問增強 mapping a region,locl a region,絕對位置讀取
9
. AIO Reactor(基於事件)和Proactor
下面列一些示例:
2
.1IO and New IO 監聽檔案系統變化通知
通過FileSystems.getDefault().newWatchService()獲取watchService,然後將需要監聽的path目錄註冊到這個watchservice中,對於這個目錄的檔案修改,新增,刪除等實踐可以配置,然後就自動能監聽到響應的事件。
private
WatchService watcher;
public
TestWatcherService(Path path)
throws
IOException {
watcher = FileSystems.getDefault().newWatchService();
path.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
}
public
void
handleEvents()
throws
InterruptedException {
while
(
true
) {
WatchKey key = watcher.take();
for
(WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind kind = event.kind();
if
(kind == OVERFLOW) {
// 事件可能lost or discarded
continue
;
}
WatchEvent<Path> e = (WatchEvent<Path>) event;
Path fileName = e.context();
System.out.printf(
"Event %s has happened,which fileName is %s%n"
,kind.name(), fileName);
}
if
(!key.reset()) {
break
;
}
2.2
IO and New IO遍歷檔案樹 ,通過繼承SimpleFileVisitor類,實現事件遍歷目錄樹的操作,然後通過Files.walkFileTree(listDir, opts, Integer.MAX_VALUE, walk);這個API來遍歷目錄樹
private
void
workFilePath() {
Path listDir = Paths.get(
"/tmp"
);
// define the starting file
ListTree walk =
new
ListTree();
…Files.walkFileTree(listDir, walk);…
// 遍歷的時候跟蹤連結
EnumSet opts = EnumSet.of(FileVisitOption.FOLLOW_LINKS);
try
{
Files.walkFileTree(listDir, opts, Integer.MAX_VALUE, walk);
}
catch
(IOException e) {
System.err.println(e);
}
class
ListTree
extends
SimpleFileVisitor<Path> {
// NIO2 遞迴遍歷檔案目錄的介面
@Override
public
FileVisitResult postVisitDirectory(Path dir, IOException exc) {
System.out.println(
"Visited directory: "
+ dir.toString());
return
FileVisitResult.CONTINUE;
}
@Override
public
FileVisitResult visitFileFailed(Path file, IOException exc) {
System.out.println(exc);
return
FileVisitResult.CONTINUE;
}
}
2.3
AIO非同步IO 檔案和網路 非同步IO在java
NIO2實現了,都是用AsynchronousFileChannel,AsynchronousSocketChanne等實現,關於同步阻塞IO,同步非阻塞IO,非同步阻塞IO和非同步非阻塞IO在ppt的這頁上下面備註有說明,有興趣的可以深入瞭解下。Java NIO2中就實現了作業系統的非同步非阻塞IO。
// 使用AsynchronousFileChannel.open(path, withOptions(),
// taskExecutor))這個API對非同步檔案IO的處理
public
static
void
asyFileChannel2() {
final
int
THREADS =
5
;
ExecutorService taskExecutor = Executors.newFixedThreadPool(THREADS);
String encoding = System.getProperty(
"file.encoding"
);
List<Future<ByteBuffer>> list =
new
ArrayList<>();
int
sheeps =
0
;
Path path = Paths.get(
"/tmp"
,
"store.txt"
);
try
(AsynchronousFileChannel asynchronousFileChannel = AsynchronousFileChannel
.open(path, withOptions(), taskExecutor)) {
for
(
int
i =
0
; i <
50
; i++) {
Callable<ByteBuffer> worker =
new
Callable<ByteBuffer>() {
@Override
public
ByteBuffer call()
throws
Exception {
ByteBuffer buffer = ByteBuffer
.allocateDirect(ThreadLocalRandom.current()
.nextInt(
100
,
200
));
asynchronousFileChannel.read(buffer, ThreadLocalRandom
……
3
. JDBC
4.1
3.1
.可以使用
try
-with-resources自動關閉Connection, ResultSet, 和 Statement資源物件
3.2
. RowSet
1.1
:引入RowSetFactory介面和RowSetProvider類,可以建立JDBC driver支援的各種 row sets,這裡的rowset實現其實就是將sql語句上的一些操作轉為方法的操作,封裝了一些功能。
3.3
. JDBC-ODBC驅動會在jdk8中刪除
try
(Statement stmt = con.createStatement()) {
RowSetFactory aFactory = RowSetProvider.newFactory();
CachedRowSet crs = aFactory.createCachedRowSet();
RowSetFactory rsf = RowSetProvider.newFactory(
"com.sun.rowset.RowSetFactoryImpl"
,
null
);
WebRowSet wrs = rsf.createWebRowSet();
createCachedRowSet
createFilteredRowSet
createJdbcRowSet
createJoinRowSet
createWebRowSet
4
. 併發工具增強
4.1
.fork-join
最大的增強,充分利用多核特性,將大問題分解成各個子問題,由多個cpu可以同時解決多個子問題,最後合併結果,繼承RecursiveTask,實現compute方法,然後呼叫fork計算,最後用join合併結果。
class
Fibonacci
extends
RecursiveTask<Integer> {
final
int
n;
Fibonacci(
int
n) {
this
.n = n;
}
private
int
compute(
int
small) {
final
int
[] results = {
1
,
1
,
2
,
3
,
5
,
8
,
13
,
21
,
34
,
55
,
89
};
return
results[small];
}
public
Integer compute() {
if
(n <=
10
) {
return
compute(n);
}
Fibonacci f1 =
new
Fibonacci(n -
1
);
Fibonacci f2 =
new
Fibonacci(n -
2
);
System.out.println(
"fork new thread for "
+ (n -
1
));
f1.fork();
System.out.println(
"fork new thread for "
+ (n -
2
));
f2.fork();
return
f1.join() + f2.join();
}
}
4.2
.ThreadLocalRandon 併發下隨機數生成類,保證併發下的隨機數生成的執行緒安全,實際上就是使用threadlocal
final
int
MAX =
100000
;
ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
long
start = System.nanoTime();
for
(
int
i =
0
; i < MAX; i++) {
threadLocalRandom.nextDouble();
}
long
end = System.nanoTime() - start;
System.out.println(
"use time1 : "
+ end);
long
start2 = System.nanoTime();
for
(
int
i =
0
; i < MAX; i++) {
Math.random();
}
long
end2 = System.nanoTime() - start2;
System.out.println(
"use time2 : "
+ end2);
4.3
. phaser 類似cyclebarrier和countdownlatch,不過可以動態新增資源減少資源
void
runTasks(List<Runnable> tasks) {
final
Phaser phaser =
new
Phaser(
1
);
// "1" to register self
// create and start threads
for
(
final
Runnable task : tasks) {
phaser.register();
new
Thread() {
public
void
run() {
phaser.arriveAndAwaitAdvance();
// await all creation
task.run();
}
}.start();
}
// allow threads to start and deregister self
phaser.arriveAndDeregister();
}
5
. Networking增強
新增URLClassLoader close方法,可以及時關閉資源,後續重新載入
class
檔案時不會導致資源被佔用或者無法釋放問題
URLClassLoader.newInstance(
new
URL[]{}).close();
新增Sockets Direct Protocol
繞過作業系統的資料拷貝,將資料從一臺機器的記憶體資料通過網路直接傳輸到另外一臺機器的記憶體中
6
. Multithreaded Custom Class Loaders
解決併發下載入
class
可能導致的死鎖問題,這個是jdk1.
6
的一些新版本就解決了,jdk7也做了一些優化。有興趣可以仔細從官方文件詳細瞭解
jdk7前:
Class Hierarchy:
class
A
extends
B
class
C
extends
D
ClassLoader Delegation Hierarchy:
Custom Classloader CL1:
directly loads
class
A
delegates to custom ClassLoader CL2
for
class
B
Custom Classloader CL2:
directly loads
class
C
delegates to custom ClassLoader CL1
for
class
D
Thread
1
:
Use CL1 to load
class
A (locks CL1)
defineClass A triggers
loadClass B (
try
to lock CL2)
Thread
2
:
Use CL2 to load
class
C (locks CL2)
defineClass C triggers
loadClass D (
try
to lock CL1)
Synchronization in the ClassLoader
class
wa
jdk7
Thread
1
:
Use CL1 to load
class
A (locks CL1+A)
defineClass A triggers
loadClass B (locks CL2+B)
Thread
2
:
Use CL2 to load
class
C (locks CL2+C)
defineClass C triggers
loadClass D (locks CL1+D)
7
. Security 增強
7.1
.提供幾種 ECC-based algorithms (ECDSA/ECDH) Elliptic Curve Cryptography (ECC)
7.2
.禁用CertPath Algorithm Disabling
7.3
. JSSE (SSL/TLS)的一些增強
8
. Internationalization 增強 增加了對一些編碼的支援和增加了一些顯示方面的編碼設定等
1
. New Scripts and Characters from Unicode
6.0
.
0
2
. Extensible Support
for
ISO
4217
Currency Codes
Currency類新增:
getAvailableCurrencies
getNumericCode
getDisplayName
getDisplayName(Locale)
3
. Category Locale Support
getDefault(Locale.Category)FORMAT DISPLAY
4
. Locale Class Supports BCP47 and UTR35
UNICODE_LOCALE_EXTENSION
PRIVATE_USE_EXTENSION
Locale.Builder
getExtensionKeys()
getExtension(
char
)
getUnicodeLocaleType(String
……
5
. New NumericShaper Methods
NumericShaper.Range
getShaper(NumericShaper.Range)
getContextualShaper(Set<NumericShaper.Range>)……
9
.jvm方面的一些特性增強,下面這些特性有些在jdk6中已經存在,這裡做了一些優化和增強。
1
.Jvm支援非java的語言 invokedynamic 指令
2
. Garbage-First Collector 適合server端,多處理器下大記憶體,將heap分成大小相等的多個區域,mark階段檢測每個區域的存活物件,compress階段將存活物件最小的先做回收,這樣會騰出很多空閒區域,這樣併發回收其他區域就能減少停止時間,提高吞吐量。
3
. HotSpot效能增強
Tiered Compilation -XX:+UseTieredCompilation 多層編譯,對於經常呼叫的程式碼會直接編譯程原生代碼,提高效率
Compressed Oops 壓縮物件指標,減少空間使用
Zero-Based Compressed Ordinary Object Pointers (oops) 進一步優化零基壓縮物件指標,進一步壓縮空間
4
. Escape Analysis 逃逸分析,對於只是在一個方法使用的一些變數,可以直接將物件分配到棧上,方法執行完自動釋放記憶體,而不用通過棧的物件引用引用堆中的物件,那麼對於物件的回收可能不是那麼及時。
5
. NUMA Collector Enhancements
NUMA(Non Uniform Memory Access),NUMA在多種計算機系統中都得到實現,簡而言之,就是將記憶體分段訪問,類似於硬碟的RAID,Oracle中的分簇
10
. Java 2D Enhancements
1
. XRender-Based Rendering Pipeline -Dsun.java2d.xrender=True
2
. Support
for
OpenType/CFF Fonts GraphicsEnvironment.getAvailableFontFamilyNames
3
. TextLayout Support
for
Tibetan Script
4
. Support
for
Linux Fonts
11
. Swing Enhancements
1
. JLayer
2
. Nimbus Look & Feel
3
. Heavyweight and Lightweight Components
4
. Shaped and Translucent Windows
5
. Hue-Saturation-Luminance (HSL) Color Selection in JColorChooser Class
12
. Jdk8 lambda表示式 最大的新增的特性,不過在很多動態語言中都已經原生支援。
原來這麼寫:
btn.setOnAction(
new
EventHandler<ActionEvent>() {
@Override
public
void
handle(ActionEvent event) {
System.out.println(
"Hello World!"
);
}
});
jdk8直接可以這麼寫:
btn.setOnAction(
event -> System.out.println(
"Hello World!"
)
);
更多示例:
public
class
Utils {
public
static
int
compareByLength(String in, String out){
return
in.length() - out.length();
}
}
public
class
MyClass {
public
void
doSomething() {
String[] args =
new
String[] {
"microsoft"
,
"apple"
,
"linux"
,
"oracle"
}
Arrays.sort(args, Utils::compareByLength);
}
}
13
.jdk8的一些其他特性,當然jdk8的增強功能還有很多,大家可以參考https:
//openjdk.java.net/projects/jdk8/
用Metaspace代替PermGen
動態擴充套件,可以設定最大值,限制於本地記憶體的大小
Parallel array sorting 新APIArrays#parallelSort.
New Date & Time API
Clock clock = Clock.systemUTC();
//return the current time based on your system clock and set to UTC.
Clock clock = Clock.systemDefaultZone();
//return time based on system clock zone
long
time = clock.millis();
//time in milliseconds from January 1st, 1970