Java 5~11各个版本新特性

Java5
Java5开发代号为Tiger(老虎),于2004-09-30发行
特性列表
  • 泛型
  • 枚举
  • 自动装箱拆箱
  • 可变参数
  • 注解
  • foreach循环(加强for、for/in)
  • 静态导入
  • 格式化(System.out.println 支持%s %d等格式化输出)
  • 线程框架/数据结构 JUC
  • Arrays工具类/StringBuilder/instrument
一、泛型
所谓类型擦除指的就是Java源码中的范型信息只容许停留在编译前期,而编译后的字节码文件中将再也不保留任何的范型信息。也就是说,范型信息在编译时将会被所有删除,其中范型类型的类型参数则会被替换为Object类型,并在实际使用时强制转换为指定的目标数据类型。而C++中的模板则会在编译时将模板类型中的类型参数根据所传递的指定数据类型生成相对应的目标代码。

Map<Integer, Integer> squares = new HashMap<Integer, Integer>();

java

通配符类型:避免unchecked警告,问号表示任何类型均可以接受

public void printList(List<?> list, PrintStream out) throws IOException {
for (Iterator<?> i = list.iterator(); i.hasNext(); ) {
out.println(i.next().toString());
}
}
linux

限制类型

public static <A extends Number> double sum(Box<A> box1,Box<A> box2){
double total = 0;
for (Iterator<A> i = box1.contents.iterator(); i.hasNext(); ) {
total = total + i.next().doubleValue();
}
for (Iterator<A> i = box2.contents.iterator(); i.hasNext(); ) {
total = total + i.next().doubleValue();
}
return total;
}
web

二、枚举


EnumMap

public void testEnumMap(PrintStream out) throws IOException {
// Create a map with the key and a String message
EnumMap<AntStatus, String> antMessages =
new EnumMap<AntStatus, String>(AntStatus.class);
// Initialize the map
antMessages.put(AntStatus.INITIALIZING, "Initializing Ant...");
antMessages.put(AntStatus.COMPILING, "Compiling Java classes...");
antMessages.put(AntStatus.COPYING, "Copying files...");
antMessages.put(AntStatus.JARRING, "JARring up files...");
antMessages.put(AntStatus.ZIPPING, "ZIPping up files...");
antMessages.put(AntStatus.DONE, "Build complete.");
antMessages.put(AntStatus.ERROR, "Error occurred.");
// Iterate and print messages
for (AntStatus status : AntStatus.values() ) {
out.println("For status " + status + ", message is: " +
antMessages.get(status));
}
}
shell

switch枚举

public String getDescription() {
switch(this) {
case ROSEWOOD: return "Rosewood back and sides";
case MAHOGANY: return "Mahogany back and sides";
case ZIRICOTE: return "Ziricote back and sides";
case SPRUCE: return "Sitka Spruce top";
case CEDAR: return "Wester Red Cedar top";
case AB_ROSETTE: return "Abalone rosette";
case AB_TOP_BORDER: return "Abalone top border";
case IL_DIAMONDS:
return "Diamonds and squares fretboard inlay";
case IL_DOTS:
return "Small dots fretboard inlay";
default: return "Unknown feature";
}
}
数据库

三、自动拆箱/装箱
将primitive类型转换成对应的wrapper类型:Boolean、Byte、Short、Character、Integer、Long、Float、Double
四、可变参数


private String print(Object... values) {
StringBuilder sb = new StringBuilder();
for (Object o : values) {
sb.append(o.toString())
.append(" ");
}
return sb.toString();
}
编程

五、注解


Inherited表示该注解是否对类的子类继承的方法等起做用

@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface InProgress { }

api

Target类型
Rentation表示annotation是否保留在编译过的class文件中仍是在运行时可读。
六、加强for循环 for/in


for/in循环办不到的事情:
(1)遍历同时获取index
(2)集合逗号拼接时去掉最后一个
(3)遍历的同时删除元素
七、静态导入


import static java.lang.System.err;
import static java.lang.System.out;
err.println(msg);
数组

八、print输出格式化


System.out.println("Line %d: %s%n", i++, line);
安全

九、并发支持(JUC)


线程池
uncaught exception(能够抓住多线程内的异常)

class SimpleThreadExceptionHandler implements
Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread t, Throwable e) {
System.err.printf("%s: %s at line %d of %s%n",
t.getName(),
e.toString(),
e.getStackTrace()[0].getLineNumber(),
e.getStackTrace()[0].getFileName());
}

服务器

blocking queue(BlockingQueue)
JUC类库
十、Arrays、Queue、线程安全StringBuilder


Arrays工具类

Arrays.sort(myArray);
Arrays.toString(myArray)
Arrays.binarySearch(myArray, 98)
Arrays.deepToString(ticTacToe)
Arrays.deepEquals(ticTacToe, ticTacToe3)

Queue
避开集合的add/remove操做,使用offer、poll操做(不抛异常)
Queue接口与List、Set同一级别,都是继承了Collection接口。LinkedList实现了Deque接口。

Queue q = new LinkedList(); //采用它来实现queue

Override返回类型
单线程StringBuilder
java.lang.instrument
Java 6


Java6开发代号为Mustang(野马),于2006-12-11发行。评价:鸡肋的版本,有JDBC4.0更新、Complier API、WebSevice支持的增强等更新。


一、Web Services
优先支持编写 XML web service 客户端程序。你能够用过简单的annotaion将你的API发布成.NET交互的web services. Mustang 添加了新的解析和 XML 在 Java object-mapping APIs中, 以前只在Java EE平台实现或者Java Web Services Pack中提供.
二、Scripting(开启JS的支持,算是比较有用的)
如今你能够在Java源代码中混入JavaScript了,这对开发原型颇有有用,你也能够插入本身的脚本引擎。
三、Database
Mustang 将联合绑定 Java DB (Apache Derby). JDBC 4.0 增长了许多特性例如支持XML做为SQL数据类型,更好的集成Binary Large OBjects (BLOBs) 和 Character Large OBjects (CLOBs) .
四、More Desktop APIs
GUI 开发者能够有更多的技巧来使用 SwingWorker utility ,以帮助GUI应用中的多线程。, JTable 分类和过滤,以及添加splash闪屏。
很显然,这对于主攻服务器开发的Java来讲,并无太多吸引力
五、Monitoring and Management.
绑定了不是很知名的 memory-heap 分析工具Jhat 来查看内核导出。
六、Compiler Access(这个很厉害)
compiler API提供编程访问javac,能够实现进程内编译,动态产生Java代码。
七、Pluggable Annotation
八、Desktop Deployment.
Swing拥有更好的 look-and-feel , LCD 文本呈现, 总体GUI性能的提高。Java应用程序能够和本地平台更好的集成,例如访问平台的系统托盘和开始菜单。Mustang将Java插件技术和Java Web Start引擎统一了起来。
九、Security
XML-数字签名(XML-DSIG) APIs 用于建立和操纵数字签名); 新的方法来访问本地平台的安全服务
十、The -ilities(很好的习惯)
质量,兼容性,稳定性。 80,000 test cases 和数百万行测试代码(只是测试活动中的一个方面). Mustang 的快照发布已经被下载15个月了,每一步中的Bug都被修复了,表现比J2SE 5还要好。
Java 7


特性列表
  • switch中添加对String类型的支持
  • 数字字面量的改进 / 数值可加下划
  • 异常处理(捕获多个异常) try-with-resources
  • 加强泛型推断
  • JSR203 NIO2.0(AIO)新IO的支持
  • JSR292与InvokeDynamic指令
  • Path接口、DirectoryStream、Files、WatchService(重要接口更新)
  • fork/join framework
一、switch中添加对String类型的支持

String title = "";
switch (gender) {
case "男":
title = name + " 先生";
break;
case "女":
title = name + " 女士";
break;
default:
title = name;
}
return title;
}

编译器在编译时先作处理:
①case仅仅有一种状况。直接转成if。
②假设仅仅有一个case和default,则直接转换为if…else…。
③有多个case。先将String转换为hashCode,而后相应的进行处理,JavaCode在底层兼容Java7曾经版本号。
二、数字字面量的改进
Java7前支持十进制(123)、八进制(0123)、十六进制(0X12AB)
Java7添加二进制表示(0B1111000一、0b11110001)
数字中可加入分隔符
Java7中支持在数字量中间添加’_'做为分隔符。更直观,如(12_123_456)。下划线仅仅能在数字中间。编译时编译器本身主动删除数字中的下划线。

int one_million = 1_000_000;

三、异常处理(捕获多个异常) try-with-resources


catch子句可以同一时候捕获多个异常

public void testSequence() {
try {
Integer.parseInt("Hello");
}
catch (NumberFormatException | RuntimeException e) { //使用'|'切割,多个类型,一个对象e
}

try-with-resources语句
Java7以前需要在finally中关闭socket、文件、数据库链接等资源;
Java7中在try语句中申请资源,实现资源的本身主动释放(资源类必须实现java.lang.AutoCloseable接口,通常的文件、数据库链接等均已实现该接口,close方法将被本身主动调用)。

public void read(String filename) throws IOException {
try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
StringBuilder builder = new StringBuilder();
String line = null;
while((line=reader.readLine())!=null){
builder.append(line);
builder.append(String.format("%n"));
}
return builder.toString();
}
}

四、加强泛型推断


Map<String, List<String>> map = new HashMap<String, List<String>>();

Java7以后能够简单的这么写

Map<String, List<String>> anagrams = new HashMap<>();

五、NIO2.0(AIO)新IO的支持


bytebuffer

public class ByteBufferUsage {
public void useByteBuffer() {
ByteBuffer buffer = ByteBuffer.allocate(32);
buffer.put((byte)1);
buffer.put(new byte[3]);
buffer.putChar('A');
buffer.putFloat(0.0f);
buffer.putLong(10, 100L);
System.out.println(buffer.getChar(4));
System.out.println(buffer.remaining());
}
public void byteOrder() {
ByteBuffer buffer = ByteBuffer.allocate(4);
buffer.putInt(1);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.getInt(0); //值为16777216
}
public void compact() {
ByteBuffer buffer = ByteBuffer.allocate(32);
buffer.put(new byte[16]);
buffer.flip();
buffer.getInt();
buffer.compact();
int pos = buffer.position();
}
public void viewBuffer() {
ByteBuffer buffer = ByteBuffer.allocate(32);
buffer.putInt(1);
IntBuffer intBuffer = buffer.asIntBuffer();
intBuffer.put(2);
int value = buffer.getInt(); //值为2
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
ByteBufferUsage bbu = new ByteBufferUsage();
bbu.useByteBuffer();
bbu.byteOrder();
bbu.compact();
bbu.viewBuffer();
}
}

filechannel

public class FileChannelUsage {
public void openAndWrite() throws IOException {
FileChannel channel = FileChannel.open(Paths.get("my.txt"), StandardOpenOption.CREATE, StandardOpenOption.WRITE);
ByteBuffer buffer = ByteBuffer.allocate(64);
buffer.putChar('A').flip();
channel.write(buffer);
}
public void readWriteAbsolute() throws IOException {
FileChannel channel = FileChannel.open(Paths.get("absolute.txt"), StandardOpenOption.READ, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
ByteBuffer writeBuffer = ByteBuffer.allocate(4).putChar('A').putChar('B');
writeBuffer.flip();
channel.write(writeBuffer, 1024);
ByteBuffer readBuffer = ByteBuffer.allocate(2);
channel.read(readBuffer, 1026);
readBuffer.flip();
char result = readBuffer.getChar(); //值为'B'
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws IOException {
FileChannelUsage fcu = new FileChannelUsage();
fcu.openAndWrite();
fcu.readWriteAbsolute();
}
}

六、JSR292与InvokeDynamic


JSR 292: Supporting Dynamically Typed Languages on the JavaTM Platform,支持在JVM上运行动态类型语言。在字节码层面支持了InvokeDynamic。

public class ThreadPoolManager {
private final ScheduledExecutorService stpe = Executors
.newScheduledThreadPool(2);
private final BlockingQueue<WorkUnit<String>> lbq;
public ThreadPoolManager(BlockingQueue<WorkUnit<String>> lbq_) {
lbq = lbq_;
}
public ScheduledFuture<?> run(QueueReaderTask msgReader) {
msgReader.setQueue(lbq);
return stpe.scheduleAtFixedRate(msgReader, 10, 10, TimeUnit.MILLISECONDS);
}
private void cancel(final ScheduledFuture<?> hndl) {
stpe.schedule(new Runnable() {
public void run() {
hndl.cancel(true);
}
}, 10, TimeUnit.MILLISECONDS);
}
/**
* 使用传统的反射api
*/
public Method makeReflective() {
Method meth = null;
try {
Class<?>[] argTypes = new Class[]{ScheduledFuture.class};
meth = ThreadPoolManager.class.getDeclaredMethod("cancel", argTypes);
meth.setAccessible(true);
} catch (IllegalArgumentException | NoSuchMethodException
| SecurityException e) {
e.printStackTrace();
}
return meth;
}
/**
* 使用代理类
* @return
*/
public CancelProxy makeProxy() {
return new CancelProxy();
}
/**
* 使用Java7的新api,MethodHandle
* invoke virtual 动态绑定后调用 obj.xxx
* invoke special 静态绑定后调用 super.xxx
* @return
*/
public MethodHandle makeMh() {
MethodHandle mh;
MethodType desc = MethodType.methodType(void.class, ScheduledFuture.class);
try {
mh = MethodHandles.lookup().findVirtual(ThreadPoolManager.class,
"cancel", desc);
} catch (NoSuchMethodException | IllegalAccessException e) {
throw (AssertionError) new AssertionError().initCause(e);
}
return mh;
}
public static class CancelProxy {
private CancelProxy() {
}
public void invoke(ThreadPoolManager mae_, ScheduledFuture<?> hndl_) {
mae_.cancel(hndl_);
}
}
}

调用invoke

public class ThreadPoolMain {
/**
* 若是被继承,还能在静态上下文寻找正确的class
*/
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private ThreadPoolManager manager;
public static void main(String[] args) {
ThreadPoolMain main = new ThreadPoolMain();
main.run();
}
private void cancelUsingReflection(ScheduledFuture<?> hndl) {
Method meth = manager.makeReflective();
try {
System.out.println("With Reflection");
meth.invoke(hndl);
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
e.printStackTrace();
}
}

private void cancelUsingProxy(ScheduledFuture<?> hndl) {
CancelProxy proxy = manager.makeProxy();
System.out.println("With Proxy");
proxy.invoke(manager, hndl);
}
private void cancelUsingMH(ScheduledFuture<?> hndl) {
MethodHandle mh = manager.makeMh();
try {
System.out.println("With Method Handle");
mh.invokeExact(manager, hndl);
} catch (Throwable e) {
e.printStackTrace();
}
}
private void run() {
BlockingQueue<WorkUnit<String>> lbq = new LinkedBlockingQueue<>();
manager = new ThreadPoolManager(lbq);
final QueueReaderTask msgReader = new QueueReaderTask(100) {
@Override
public void doAction(String msg_) {
if (msg_ != null)
System.out.println("Msg recvd: " + msg_);
}
};
ScheduledFuture<?> hndl = manager.run(msgReader);
cancelUsingMH(hndl);
// cancelUsingProxy(hndl);
// cancelUsingReflection(hndl);
}
}

七、Path接口(重要接口更新)


Path

public class PathUsage {
public void usePath() {
Path path1 = Paths.get("folder1", "sub1");
Path path2 = Paths.get("folder2", "sub2");
path1.resolve(path2); //folder1sub1 older2sub2
path1.resolveSibling(path2); //folder1 older2sub2
path1.relativize(path2); //.... older2sub2
path1.subpath(0, 1); //folder1
path1.startsWith(path2); //false
path1.endsWith(path2); //false
Paths.get("folder1/./../folder2/my.text").normalize(); //folder2my.text
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
PathUsage usage = new PathUsage();
usage.usePath();
}
}

DirectoryStream

public class ListFile {
public void listFiles() throws IOException {
Path path = Paths.get("");
try (DirectoryStream<Path> stream = Files.newDirectoryStream(path, "*.*")) {
for (Path entry: stream) {
//使用entry
System.out.println(entry);
}
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws IOException {
ListFile listFile = new ListFile();
listFile.listFiles();
}
}

Files

public class FilesUtils {
public void manipulateFiles() throws IOException {
Path newFile = Files.createFile(Paths.get("new.txt").toAbsolutePath());
List<String> content = new ArrayList<String>();
content.add("Hello");
content.add("World");
Files.write(newFile, content, Charset.forName("UTF-8"));
Files.size(newFile);
byte[] bytes = Files.readAllBytes(newFile);
ByteArrayOutputStream output = new ByteArrayOutputStream();
Files.copy(newFile, output);
Files.delete(newFile);
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws IOException {
FilesUtils fu = new FilesUtils();
fu.manipulateFiles();
}
}

WatchService

public class WatchAndCalculate {
public void calculate() throws IOException, InterruptedException {
WatchService service = FileSystems.getDefault().newWatchService();
Path path = Paths.get("").toAbsolutePath();
path.register(service, StandardWatchEventKinds.ENTRY_CREATE);
while (true) {
WatchKey key = service.take();
for (WatchEvent<?> event : key.pollEvents()) {
Path createdPath = (Path) event.context();
createdPath = path.resolve(createdPath);
long size = Files.size(createdPath);
System.out.println(createdPath + " ==> " + size);
}
key.reset();
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws Throwable {
WatchAndCalculate wc = new WatchAndCalculate();
wc.calculate();
}
}

八、fork/join计算框架


Java7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每一个小任务结果后获得大任务结果的框架。
该框架为Java8的并行流打下了坚实的基础


Java 8


Java 8可谓是自Java 5以来最具革命性的版本了,她在语言、编译器、类库、开发工具以及Java虚拟机等方面都带来了很多新特性。


1、Lambda表达式


Lambda表达式能够说是Java 8最大的卖点,她将函数式编程引入了Java。Lambda容许把函数做为一个方法的参数,或者把代码当作数据。
一个Lambda表达式能够由用逗号分隔的参数列表、–>符号与函数体三部分表示。例如:

Arrays.asList( "p", "k", "u","f", "o", "r","k").forEach( e -> System.out.println( e ) );

为了使现有函数更好的支持Lambda表达式,Java 8引入了函数式接口的概念。函数式接口就是只有一个方法的普通接口。java.lang.Runnable与java.util.concurrent.Callable是函数式接口最典型的例子。为此,Java 8增长了一种特殊的注解@FunctionalInterface
2、接口的默认方法与静态方法


咱们能够在接口中定义默认方法,使用default关键字,并提供默认的实现。全部实现这个接口的类都会接受默认方法的实现,除非子类提供的本身的实现。例如:

public interface DefaultFunctionInterface {
default String defaultFunction() {
return "default function";
}
}

咱们还能够在接口中定义静态方法,使用static关键字,也能够提供实现。例如:

public interface StaticFunctionInterface {
static String staticFunction() {
return "static function";
}
}

接口的默认方法和静态方法的引入,其实能够认为引入了C++中抽象类的理念,之后咱们不再用在每一个实现类中都写重复的代码了。
3、方法引用(含构造方法引用)


一般与Lambda表达式联合使用,能够直接引用已有Java类或对象的方法。通常有四种不一样的方法引用:
构造器引用。语法是Class::new,或者更通常的Class< T >::new,要求构造器方法是没有参数;
静态方法引用。语法是Class::static_method,要求接受一个Class类型的参数;
特定类的任意对象方法引用。它的语法是Class::method。要求方法是没有参数的;
特定对象的方法引用,它的语法是instance::method。要求方法接受一个参数,与3不一样的地方在于,3是在列表元素上分别调用方法,而4是在某个对象上调用方法,将列表元素做为参数传入;
4、重复注解


在Java 5中使用注解有一个限制,即相同的注解在同一位置只能声明一次。Java 8引入重复注解,这样相同的注解在同一地方也能够声明屡次。重复注解机制自己须要用@Repeatable注解。Java 8在编译器层作了优化,相同注解会以集合的方式保存,所以底层的原理并无变化。
5、扩展注解的支持(类型注解)


Java 8扩展了注解的上下文,几乎能够为任何东西添加注解,包括局部变量、泛型类、父类与接口的实现,连方法的异常也能添加注解。

private @NotNull String name;

6、Optional


Java 8引入Optional类来防止空指针异常,Optional类最早是由Google的Guava项目引入的。Optional类其实是个容器:它能够保存类型T的值,或者保存null。使用Optional类咱们就不用显式进行空指针检查了。
7、Stream
Stream API是把真正的函数式编程风格引入到Java中。其实简单来讲能够把Stream理解为MapReduce,固然Google的MapReduce的灵感也是来自函数式编程。她实际上是一连串支持连续、并行汇集操做的元素。从语法上看,也很像linux的管道、或者链式编程,代码写起来简洁明了,很是酷帅!
8、Date/Time API (JSR 310)


Java 8新的Date-Time API (JSR 310)受Joda-Time的影响,提供了新的java.time包,能够用来替代 java.util.Date和java.util.Calendar。通常会用到Clock、LocaleDate、LocalTime、LocaleDateTime、ZonedDateTime、Duration这些类,对于时间日期的改进仍是很是不错的。
9、JavaScript引擎Nashorn


Nashorn容许在JVM上开发运行JavaScript应用,容许Java与JavaScript相互调用。
10、Base64


在Java 8中,Base64编码成为了Java类库的标准。Base64类同时还提供了对URL、MIME友好的编码器与解码器。
说在后面
除了这十大特性,还有另外的一些新特性:
更好的类型推测机制:Java 8在类型推测方面有了很大的提升,这就使代码更整洁,不须要太多的强制类型转换了。
编译器优化:Java 8将方法的参数名加入了字节码中,这样在运行时经过反射就能获取到参数名,只须要在编译时使用-parameters参数。
并行(parallel)数组:支持对数组进行并行处理,主要是parallelSort()方法,它能够在多核机器上极大提升数组排序的速度。
并发(Concurrency):在新增Stream机制与Lambda的基础之上,加入了一些新方法来支持汇集操做。
Nashorn引擎jjs:基于Nashorn引擎的命令行工具。它接受一些JavaScript源代码为参数,而且执行这些源代码。
类依赖分析器jdeps:能够显示Java类的包级别或类级别的依赖。
JVM的PermGen空间被移除:取代它的是Metaspace(JEP 122)。
Java 9


通过4次跳票,历经曲折的java 9 终于终于在2017年9月21日发布(距离上个版本足足3年半时间)java 9 提供了超过 150 项新功能特性,包括备受期待的模块化系统、可交互的 REPL 工具:jshell,JDK 编译工具,Java 公共 API 和私有代码,以及安全加强、扩展提高、性能管理改善等。能够说 Java 9 是一个庞大的系统工程,彻底作了一个总体改变。但本博文只介绍最重要的十大新特性
特性列表
  • 平台级modularity(原名:Jigsaw) 模块化系统
  • Java 的 REPL 工具: jShell 命令
  • 多版本兼容 jar 包(这个在处理向下兼容方面,很是好用)
  • 语法改进:接口的私有方法
  • 语法改进:UnderScore(下划线)使用的限制
  • 底层结构:String 存储结构变动(这个很重要)
  • 集合工厂方法:快速建立只读集合
  • 加强的 Stream API
  • 全新的 HTTP 客户端 API
  • 其它特性
  • 它的新特性来自于100于项JEP和40于项JSR


Java 10


2018年3月20日,Java 10 正式发布,这一次没有跳票。它号称有109项新特性,包含12个JEP。须要注意的是,本次Java10并非Oracle的官方LTS版本,仍是坐等java11的发布再考虑在生产中使用
特性列表
  • 局部变量的类型推断 var关键字
  • GC改进和内存管理 并行全垃圾回收器 G1
  • 垃圾回收器接口
  • 线程-局部变量管控
  • 合并 JDK 多个代码仓库到一个单独的储存库中
  • 新增API:ByteArrayOutputStream
  • 新增API:List、Map、Set
  • 新增API:java.util.Properties
  • 新增API: Collectors收集器
  • 其它特性
一、局部变量的类型推断 var关键字


这个新功能将为Java增长一些语法糖 - 简化它并改善开发者体验。新的语法将减小与编写Java相关的冗长度,同时保持对静态类型安全性的承诺。
这多是Java10给开发者带来的最大的一个新特性。下面主要看例子:

public static void main(String[] args) {
var list = new ArrayList<String>();
list.add("hello,world!");
System.out.println(list);
}

这是最日常的使用。注意赋值语句右边,最好写上泛型类型,不然会有以下状况:

public static void main(String[] args) {
var list = new ArrayList<>();
list.add("hello,world!");
list.add(1);
list.add(1.01);
System.out.println(list);
}

list什么均可以装,很是的不安全了。和js等语言不一样的是,毕竟Java仍是强类型的语言,因此下面语句是编译报错的:

public static void main(String[] args) {
var list = new ArrayList<String>();
list.add("hello,world!");
System.out.println(list);
list = new ArrayList<Integer>(); //编译报错
}

注意:下面几点使用限制
局部变量初始化
for循环内部索引变量
传统的for循环声明变量

public static void main(String[] args) {
//局部变量初始化
var list = new ArrayList<String>();
//for循环内部索引变量
for (var s : list) {
System.out.println(s);
}
//传统的for循环声明变量
for (var i = 0; i < list.size(); i++) {
System.out.println(i);
}
}

下面这几种状况,都是不能使用var的
方法参数全局变量
public static var list = new ArrayList<String>(); //编译报错
public static List<String> list = new ArrayList<>(); //正常编译经过
构造函数参数方法返回类型字段捕获表达式(或任何其余类型的变量声明)


二、GC改进和内存管理 并行全垃圾回收器 G1


JDK 10中有2个JEP专门用于改进当前的垃圾收集元素。
Java 10的第二个JEP是针对G1的并行彻底GC(JEP 307),其重点在于经过彻底GC并行来改善G1最坏状况的等待时间。G1是Java 9中的默认GC,而且此JEP的目标是使G1平行。
三、垃圾回收器接口


这不是让开发者用来控制垃圾回收的接口;而是一个在 JVM 源代码中的容许另外的垃圾回收器快速方便的集成的接口。
四、线程-局部变量管控


这是在 JVM 内部至关低级别的更改,如今将容许在不运行全局虚拟机安全点的状况下实现线程回调。这将使得中止单个线程变得可能和便宜,而不是只能启用或中止全部线程。
五、合并 JDK 多个代码仓库到一个单独的储存库中


在 JDK9 中,有 8 个仓库: root、corba、hotspot、jaxp、jaxws、jdk、langtools 和 nashorn 。在 JDK10 中这些将被合并为一个,使得跨相互依赖的变动集的存储库运行 atomic commit (原子提交)成为可能。
六、新增API:ByteArrayOutputStream


String toString(Charset): 重载 toString(),经过使用指定的字符集解码字节,将缓冲区的内容转换为字符串。
七、新增API:List、Map、Set


这3个接口都增长了一个新的静态方法,copyOf(Collection)。这些函数按照其迭代顺序返回一个不可修改的列表、映射或包含给定集合的元素的集合。
八、新增API:java.util.Properties


增长了一个新的构造函数,它接受一个 int 参数。这将建立一个没有默认值的空属性列表,而且指定初始大小以容纳指定的元素数量,而无需动态调整大小。还有一个新的重载的 replace 方法,接受三个 Object 参数并返回一个布尔值。只有在当前映射到指定值时,才会替换指定键的条目。
九、新增API: Collectors收集器


toUnmodifiableList():
toUnmodifiableSet():
toUnmodifiableMap(Function, Function):
toUnmodifiableMap(Function, Function, BinaryOperator):
这四个新方法都返回 Collectors ,将输入元素汇集到适当的不可修改的集合中。
十、其它特性


线程本地握手(JEP 312)
其余Unicode语言 - 标记扩展(JEP 314)
基于Java的实验性JIT编译器
根证书颁发认证(CA)
删除工具javah(JEP 313)
从JDK中移除了javah工具,这个很简单而且很重要。
最后


JDK10的升级幅度其实主要仍是以优化为主,并无带来太多对使用者惊喜的特性。因此建议广大开发者仍是坐等Java11吧,预计2018年9月份就会到来,最重要的是它是LTS版本哦,因此是能够运用在生产上的。
Java 11


2018年9月26日,Oracle 官方宣布 Java 11 正式发布。这是 Java 大版本周期变化后的第一个长期支持版本(LTS版本,Long-Term-Support,持续支持到2026年9月),很是值得关注。Java11 带来了 ZGC、Http Client 等重要特性,一共包含 17 个 JEP(JDK Enhancement Proposals,JDK 加强提案)。



特性列表
官方新特性:




本文针对于读者对关心、也是最实用的八大新特性作出一些讲解
  • 本地变量类型推断
  • 字符串增强
  • 集合增强
  • Stream 增强
  • Optional 增强
  • InputStream 增强
  • HTTP Client API
  • 化繁为简,一个命令编译运行源代码






三、集合增强


自 Java 9 开始,Jdk 里面为集合(List/ Set/ Map)都添加了 of 和 copyOf 方法,它们两个都用来建立不可变的集合,来看下它们的使用和区别。
示例1:

var list = List.of("Java", "Python", "C");
var copy = List.copyOf(list);
System.out.println(list == copy); // true

示例2:

var list = new ArrayList<String>();
var copy = List.copyOf(list);
System.out.println(list == copy); // false

示例1和2代码差很少,为何一个为true,一个为false?
来看下它们的源码:

static <E> List<E> of(E... elements) {
switch (elements.length) { // implicit null check of elements
case 0:
return ImmutableCollections.emptyList();
case 1:
return new ImmutableCollections.List12<>(elements[0]);
case 2:
return new ImmutableCollections.List12<>(elements[0], elements[1]);
default:
return new ImmutableCollections.ListN<>(elements);
}
}
static <E> List<E> copyOf(Collection<? extends E> coll) {
return ImmutableCollections.listCopy(coll);
}
static <E> List<E> listCopy(Collection<? extends E> coll) {
if (coll instanceof AbstractImmutableList && coll.getClass() != SubList.class) {
return (List<E>)coll;
} else {
return (List<E>)List.of(coll.toArray());
}
}

能够看出 copyOf 方法会先判断来源集合是否是 AbstractImmutableList 类型的,若是是,就直接返回,若是不是,则调用 of 建立一个新的集合。
示例2由于用的 new 建立的集合,不属于不可变 AbstractImmutableList 类的子类,因此 copyOf 方法又建立了一个新的实例,因此为false.
注意:使用of和copyOf建立的集合为不可变集合,不能进行添加、删除、替换、排序等操做,否则会报 java.lang.UnsupportedOperationException 异常。
上面演示了 List 的 of 和 copyOf 方法,Set 和 Map 接口都有。

public static void main(String[] args) {
Set<String> names = Set.of("Fred", "Wilma", "Barney", "Betty");
//JDK11以前咱们只能这么写
System.out.println(Arrays.toString(names.toArray(new String[names.size()])));
//JDK11以后 能够直接这么写了
System.out.println(Arrays.toString(names.toArray(size -> new String[size])));
System.out.println(Arrays.toString(names.toArray(String[]::new)));
}

Collection.toArray(IntFunction)
在java.util.Collection接口中添加了一个新的默认方法toArray(IntFunction)。此方法容许将集合的元素传输到新建立的所需运行时类型的数组。

public static void main(String[] args) {
Set<String> names = Set.of("Fred", "Wilma", "Barney", "Betty");
//JDK11以前咱们只能这么写
System.out.println(Arrays.toString(names.toArray(new String[names.size()])));
//JDK11以后 能够直接这么写了
System.out.println(Arrays.toString(names.toArray(size -> new String[size])));
System.out.println(Arrays.toString(names.toArray(String[]::new)));
}

四、Stream 增强
Stream 是 Java 8 中的新特性,Java 9 开始对 Stream 增长了如下 4 个新方法。
增长单个参数构造方法,可为null

Stream.ofNullable(null).count(); // 0
//JDK8木有ofNullable方法哦

源码可看看:

/**
* @since 9
*/
public static<T> Stream<T> ofNullable(T t) {
return t == null ? Stream.empty()
: StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
}

二、增长 takeWhile 和 dropWhile 方法

Stream.of(1, 2, 3, 2, 1)
.takeWhile(n -> n < 3)
.collect(Collectors.toList()); // [1, 2]

takeWhile表示从开始计算,当 n < 3 时就截止。

Stream.of(1, 2, 3, 2, 1)
.dropWhile(n -> n < 3)
.collect(Collectors.toList()); // [3, 2, 1]

3)iterate重载
这个 iterate 方法的新重载方法,可让你提供一个 Predicate (判断条件)来指定何时结束迭代。

public static void main(String[] args) {
// 这构造的是无限流 JDK8开始
Stream.iterate(0, (x) -> x + 1);
// 这构造的是小于10就结束的流 JDK9开始
Stream.iterate(0, x -> x < 10, x -> x + 1);
}

五、Optional 增强


Opthonal 也增长了几个很是酷的方法,如今能够很方便的将一个 Optional 转换成一个 Stream, 或者当一个空 Optional 时给它一个替代的。

Optional.of("javastack").orElseThrow(); // javastack
Optional.of("javastack").stream().count(); // 1
Optional.ofNullable(null)
.or(() -> Optional.of("javastack"))
.get(); // javastac

or方法和stream方法显然都是新增的
六、InputStream 增强


InputStream 终于有了一个很是有用的方法:transferTo,能够用来将数据直接传输到 OutputStream,这是在处理原始数据流时很是常见的一种用法,以下示例。

var classLoader = ClassLoader.getSystemClassLoader();
var inputStream = classLoader.getResourceAsStream("javastack.txt");
var javastack = File.createTempFile("javastack2", "txt");
try (var outputStream = new FileOutputStream(javastack)) {
inputStream.transferTo(outputStream);
}

七、HTTP Client API(重磅)


在java9及10被标记incubator的模块jdk.incubator.httpclient,在java11被标记为正式,改成java.net.http模块。这是 Java 9 开始引入的一个处理 HTTP 请求的的孵化 HTTP Client API,该 API 支持同步和异步,而在 Java 11 中已经为正式可用状态,你能够在 java.net 包中找到这个 API。
来看一下 HTTP Client 的用法:
上面的 .GET() 能够省略,默认请求方式为 Get!
更多使用示例能够看这个 API,后续有机会再作演示。
如今 Java 自带了这个 HTTP Client API,咱们之后还有必要用 Apache 的 HttpClient 工具包吗?我以为没啥必要了
八、化繁为简,一个命令编译运行源代码


看下面的代码。

// 编译
javac Javastack.java
// 运行
java Javastack

在咱们的认知里面,要运行一个 Java 源代码必须先编译,再运行,两步执行动做。而在将来的 Java 11 版本中,经过一个 java 命令就直接搞定了,如如下所示。

java Javastack.java

移除项
移除了com.sun.awt.AWTUtilities
移除了sun.misc.Unsafe.defineClass,
使用 java.lang.invoke.MethodHandles.Lookup.defineClass来替代
移除了Thread.destroy()以及 Thread.stop(Throwable)方法移除了
sun.nio.ch.disableSystemWideOverlappingFileLockCheck、sun.locale.formatasdefault属性
移除了jdk.snmp模块
移除了javafx,openjdk估计是从java10版本就移除了,oracle jdk10还还没有移除javafx,而java11版本则oracle的jdk版本也移除了javafx
移除了Java Mission Control,从JDK中移除以后,须要本身单独下载
移除了这些Root Certificates :Baltimore Cybertrust Code Signing CA,SECOM ,AOL and Swisscom
废弃项


废弃了Nashorn JavaScript Engine
废弃了-XX+AggressiveOpts选项
-XX:+UnlockCommercialFeatures以及
-XX:+LogCommercialFeatures选项也不- 再须要
废弃了Pack200工具及其API
说到最后


java11是java改成6个月发布一版的策略以后的第一个LTS(Long-Term Support)版本(oracle版本才有LTS),这个版本最主要的特性是:在模块方面移除Java EE以及CORBA模块,在JVM方面引入了实验性的ZGC,在API方面正式提供了HttpClient类。
从java11版本开始,再也不单独发布JRE或者Server JRE版本了,有须要的能够本身经过jlink去定制runtime image
备注:ZGC做为实验性功能包含在内。要启用它,所以须要将-XX:+ UnlockExperimentalVMOptions选项与-XX:+ UseZGC选项结合使用。
ZGC的这个实验版具备如下限制:
  • 它仅适用于Linux / x64。
  • 不支持使用压缩的oops和/或压缩的类点。默认状况下禁用-XX:+UseCompressedOops和-XX:+UseCompressedClassPointers选项。启用它们将不起做用。
  • 不支持类卸载。默认状况下禁用-XX:+ ClassUnloading和-XX:+ - - ClassUnloadingWithConcurrentMark选项。启用它们将不起做用。
  • 不支持将ZGC与Graal结合使用。

更多技术资讯:gzitcast

相关文章
相关标签/搜索