Java5开发代号为Tiger(老虎),于2004-09-30发行
特性列表
所谓类型擦除指的就是Java源码中的范型信息只允许停留在编译前期,而编译后的字节码文件中将不再保留任何的范型信息。也就是说,范型信息在编译时将会被全部删除,其中范型类型的类型参数则会被替换为Object类型,并在实际使用时强制转换为指定的目标数据类型。而C++中的模板则会在编译时将模板类型中的类型参数根据所传递的指定数据类型生成相对应的目标代码。
Mapsquares = new HashMap ();
通配符类型:避免unchecked警告,问号表示任何类型都可以接受
public void printList(List> list, PrintStream out) throws IOException { for (Iterator> i = list.iterator(); i.hasNext(); ) { out.println(i.next().toString()); } }
限制类型
public static double sum(Box box1,Box box2){ double total = 0; for (Iterator i = box1.contents.iterator(); i.hasNext(); ) { total = total + i.next().doubleValue(); } for (Iterator i = box2.contents.iterator(); i.hasNext(); ) { total = total + i.next().doubleValue(); } return total; }
EnumMap
public void testEnumMap(PrintStream out) throws IOException { // Create a map with the key and a String message EnumMapantMessages = new EnumMap (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)); } }
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 { }
Target类型
Rentation表示annotation是否保留在编译过的class文件中还是在运行时可读。
for/in循环办不到的事情:
(1)遍历同时获取index
(2)集合逗号拼接时去掉最后一个
(3)遍历的同时删除元素
import static java.lang.System.err; import static java.lang.System.out; err.println(msg);
System.out.println("Line %d: %s%n", i++, line);
线程池
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)
10、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
Java6开发代号为Mustang(野马),于2006-12-11发行。评价:鸡肋的版本,有JDBC4.0更新、Complier API、WebSevice支持的加强等更新。
优先支持编写 XML web service 客户端程序。你可以用过简单的annotaion将你的API发布成.NET交互的web services. Mustang 添加了新的解析和 XML 在 Java object-mapping APIs中, 之前只在Java EE平台实现或者Java Web Services Pack中提供.
现在你可以在Java源代码中混入JavaScript了,这对开发原型很有有用,你也可以插入自己的脚本引擎。
Mustang 将联合绑定 Java DB (Apache Derby). JDBC 4.0 增加了许多特性例如支持XML作为SQL数据类型,更好的集成Binary Large OBjects (BLOBs) 和 Character Large OBjects (CLOBs) .
GUI 开发者可以有更多的技巧来使用 SwingWorker utility ,以帮助GUI应用中的多线程。, JTable 分类和过滤,以及添加splash闪屏。
很显然,这对于主攻服务器开发的Java来说,并没有太多吸引力
绑定了不是很知名的 memory-heap 分析工具Jhat 来查看内核导出。
compiler API提供编程访问javac,可以实现进程内编译,动态产生Java代码。
Swing拥有更好的 look-and-feel , LCD 文本呈现, 整体GUI性能的提升。Java应用程序可以和本地平台更好的集成,例如访问平台的系统托盘和开始菜单。Mustang将Java插件技术和Java Web Start引擎统一了起来。
XML-数字签名(XML-DSIG) APIs 用于创建和操纵数字签名); 新的方法来访问本地平台的安全服务
质量,兼容性,稳定性。 80,000 test cases 和数百万行测试代码(只是测试活动中的一个方面). Mustang 的快照发布已经被下载15个月了,每一步中的Bug都被修复了,表现比J2SE 5还要好。
特性列表
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添加二进制表示(0B11110001、0b11110001)
数字中可加入分隔符
Java7中支持在数字量中间添加’_'作为分隔符。更直观,如(12_123_456)。下划线仅仅能在数字中间。编译时编译器自己主动删除数字中的下划线。
int one_million = 1_000_000;
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> map = new HashMap >();
Java7之后可以简单的这么写
Map> anagrams = new HashMap<>();
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(); } }
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> lbq; public ThreadPoolManager(BlockingQueue > 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> 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
public class PathUsage { public void usePath() { Path path1 = Paths.get("folder1", "sub1"); Path path2 = Paths.get("folder2", "sub2"); path1.resolve(path2); //folder1sub1older2sub2 path1.resolveSibling(path2); //folder1older2sub2 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 (DirectoryStreamstream = 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()); Listcontent = new ArrayList (); 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(); } }
Java7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。
该框架为Java8的并行流打下了坚实的基础
Java 8可谓是自Java 5以来最具革命性的版本了,她在语言、编译器、类库、开发工具以及Java虚拟机等方面都带来了不少新特性。
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
我们可以在接口中定义默认方法,使用default关键字,并提供默认的实现。所有实现这个接口的类都会接受默认方法的实现,除非子类提供的自己的实现。例如:
public interface DefaultFunctionInterface { default String defaultFunction() { return "default function"; } }
我们还可以在接口中定义静态方法,使用static关键字,也可以提供实现。例如:
public interface StaticFunctionInterface { static String staticFunction() { return "static function"; } }
接口的默认方法和静态方法的引入,其实可以认为引入了C++中抽象类的理念,以后我们再也不用在每个实现类中都写重复的代码了。
通常与Lambda表达式联合使用,可以直接引用已有Java类或对象的方法。一般有四种不同的方法引用:
构造器引用。语法是Class::new,或者更一般的Class< T >::new,要求构造器方法是没有参数;
静态方法引用。语法是Class::static_method,要求接受一个Class类型的参数;
特定类的任意对象方法引用。它的语法是Class::method。要求方法是没有参数的;
特定对象的方法引用,它的语法是instance::method。要求方法接受一个参数,与3不同的地方在于,3是在列表元素上分别调用方法,而4是在某个对象上调用方法,将列表元素作为参数传入;
在Java 5中使用注解有一个限制,即相同的注解在同一位置只能声明一次。Java 8引入重复注解,这样相同的注解在同一地方也可以声明多次。重复注解机制本身需要用@Repeatable注解。Java 8在编译器层做了优化,相同注解会以集合的方式保存,因此底层的原理并没有变化。
Java 8扩展了注解的上下文,几乎可以为任何东西添加注解,包括局部变量、泛型类、父类与接口的实现,连方法的异常也能添加注解。
private @NotNull String name;
Java 8引入Optional类来防止空指针异常,Optional类最先是由Google的Guava项目引入的。Optional类实际上是个容器:它可以保存类型T的值,或者保存null。使用Optional类我们就不用显式进行空指针检查了。
Stream API是把真正的函数式编程风格引入到Java中。其实简单来说可以把Stream理解为MapReduce,当然Google的MapReduce的灵感也是来自函数式编程。她其实是一连串支持连续、并行聚集操作的元素。从语法上看,也很像linux的管道、或者链式编程,代码写起来简洁明了,非常酷帅!
Java 8新的Date-Time API (JSR 310)受Joda-Time的影响,提供了新的java.time包,可以用来替代 java.util.Date和java.util.Calendar。一般会用到Clock、LocaleDate、LocalTime、LocaleDateTime、ZonedDateTime、Duration这些类,对于时间日期的改进还是非常不错的。
Nashorn允许在JVM上开发运行JavaScript应用,允许Java与JavaScript相互调用。
在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)。
经过4次跳票,历经曲折的java 9 终于终于在2017年9月21日发布(距离上个版本足足3年半时间)java 9 提供了超过 150 项新功能特性,包括备受期待的模块化系统、可交互的 REPL 工具:jshell,JDK 编译工具,Java 公共 API 和私有代码,以及安全增强、扩展提升、性能管理改善等。可以说 Java 9 是一个庞大的系统工程,完全做了一个整体改变。但本博文只介绍最重要的十大新特性
特性列表
详见:https://blog.csdn.net/jek123456/article/details/79693546
2018年3月20日,Java 10 正式发布,这一次没有跳票。它号称有109项新特性,包含12个JEP。需要注意的是,本次Java10并不是Oracle的官方LTS版本,还是坐等java11的发布再考虑在生产中使用
特性列表
这个新功能将为Java增加一些语法糖 - 简化它并改善开发者体验。新的语法将减少与编写Java相关的冗长度,同时保持对静态类型安全性的承诺。
这可能是Java10给开发者带来的最大的一个新特性。下面主要看例子:
public static void main(String[] args) { var list = new ArrayList(); 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(); list.add("hello,world!"); System.out.println(list); list = new ArrayList (); //编译报错 }
注意:下面几点使用限制
局部变量初始化
for循环内部索引变量
传统的for循环声明变量
public static void main(String[] args) { //局部变量初始化 var list = new ArrayList(); //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
public static List
构造函数参数方法返回类型字段捕获表达式(或任何其他类型的变量声明)
JDK 10中有2个JEP专门用于改进当前的垃圾收集元素。
Java 10的第二个JEP是针对G1的并行完全GC(JEP 307),其重点在于通过完全GC并行来改善G1最坏情况的等待时间。G1是Java 9中的默认GC,并且此JEP的目标是使G1平行。
这不是让开发者用来控制垃圾回收的接口;而是一个在 JVM 源代码中的允许另外的垃圾回收器快速方便的集成的接口。
这是在 JVM 内部相当低级别的更改,现在将允许在不运行全局虚拟机安全点的情况下实现线程回调。这将使得停止单个线程变得可能和便宜,而不是只能启用或停止所有线程。
在 JDK9 中,有 8 个仓库: root、corba、hotspot、jaxp、jaxws、jdk、langtools 和 nashorn 。在 JDK10 中这些将被合并为一个,使得跨相互依赖的变更集的存储库运行 atomic commit (原子提交)成为可能。
String toString(Charset): 重载 toString(),通过使用指定的字符集解码字节,将缓冲区的内容转换为字符串。
这3个接口都增加了一个新的静态方法,copyOf(Collection)。这些函数按照其迭代顺序返回一个不可修改的列表、映射或包含给定集合的元素的集合。
增加了一个新的构造函数,它接受一个 int 参数。这将创建一个没有默认值的空属性列表,并且指定初始大小以容纳指定的元素数量,而无需动态调整大小。还有一个新的重载的 replace 方法,接受三个 Object 参数并返回一个布尔值。只有在当前映射到指定值时,才会替换指定键的条目。
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版本哦,所以是可以运用在生产上的。
2018年9月26日,Oracle 官方宣布 Java 11 正式发布。这是 Java 大版本周期变化后的第一个长期支持版本(LTS版本,Long-Term-Support,持续支持到2026年9月),非常值得关注。Java11 带来了 ZGC、Http Client 等重要特性,一共包含 17 个 JEP(JDK Enhancement Proposals,JDK 增强提案)。
特性列表
官方新特性:
本文针对于读者对关心、也是最实用的八大新特性做出一些讲解
自 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(); var copy = List.copyOf(list); System.out.println(list == copy); // false
示例1和2代码差不多,为什么一个为true,一个为false?
来看下它们的源码:
staticList 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 List copyOf(Collection extends E> coll) { return ImmutableCollections.listCopy(coll); } static List listCopy(Collection extends E> coll) { if (coll instanceof AbstractImmutableList && coll.getClass() != SubList.class) { return (List )coll; } else { return (List )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) { Setnames = 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) { Setnames = 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 是 Java 8 中的新特性,Java 9 开始对 Stream 增加了以下 4 个新方法。
增加单个参数构造方法,可为null
Stream.ofNullable(null).count(); // 0 //JDK8木有ofNullable方法哦
源码可看看:
/** * @since 9 */ public staticStream ofNullable(T t) { return t == null ? Stream.empty() : StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false); }
2、增加 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); }
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 终于有了一个非常有用的方法: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); }
在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的这个实验版具有以下限制:
使用Java 12,switch不仅可以作为语句也可以作为表达式。 无论作为语句或者作为表达式,switch都可以使用传统/简化的作用域和控制流行为。 这将有助于简化代码,并为在switch中使用模式匹配铺平道路。
Java开发人员正在增强Java编程语言,以使用模式匹配来解决当前switch语句的几个问题。 这包括:switch块的默认控制流行为,switch块默认作用域(被视为单个作用域的块)和switch仅作为语句。
在Java 11中,switch语句追随C和C++,默认情况下使用fall-through语义。 虽然传统的控制流程在编写低级代码时很有用,但随着switch在更高级别的环境中采用,易出错会盖过其灵活性。
Java 11
Java 12
通过在64位平台上的默认类列表的帮助下生成CDS归档来改进JDK构建过程,从而有效地消除了运行java -Xshare:dump。 此功能的目标包括:1。)改进开箱即用的启动时间,以及2.)摆脱使用-Xshare:dump。
Shenandoah是一种垃圾收集(GC)算法,旨在保证低延迟(10 - 500 ms的下限)。 它通过在运行Java工作线程的同时执行GC操作减少GC暂停时间。 使用Shenandoah,暂停时间不依赖于堆的大小。 这意味着无论堆的大小如何,暂停时间都是差不多的。
这是一个实验性功能,不包含在默认(Oracle)的OpenJDK版本中。
此功能为JDK源代码添加了一套微基准测试(大约100个),简化了现有微基准测试的运行和新基准测试的创建过程。 它基于Java Microbenchmark Harness(JMH)并支持JMH更新。
此功能使开发人员可以轻松运行当前的微基准测试并为JDK源代码添加新的微基准测试。 可以基于Java Microbenchmark Harness(JMH)轻松测试JDK性能。 它将支持JMH更新,并在套件中包含一组(约100个)基准测试。
JEP 334引入了一个API,用于建模关键类文件和运行时artifacts,例如常量池。 此API将包括ClassDesc,MethodTypeDesc,MethodHandleDesc和DynamicConstantDesc等类。此 API 对于操作类和方法的工具很有帮助。
此功能通过将Mixed GC集拆分为强制部分和可选部分,使G1垃圾收集器更有效地中止垃圾收集过程。通过允许垃圾收集过程优先处理强制集,g1可以更多满足满足暂停时间目标。
G1是一个垃圾收集器,设计用于具有大量内存的多处理器机器。由于它提高了性能效率,g1垃圾收集器最终将取代cms垃圾收集器。
G1垃圾收集器的主要目标之一是满足用户设置的暂停时间。G1采用一个分析引擎来选择在收集期间要处理的工作量。此选择过程的结果是一组称为GC集的区域。一旦GC集建立并且GC已经开始,那么G1就无法停止。
如果G1发现GC集选择选择了错误的区域,它会将GC区域的拆分为两部分(强制部分和可选部分)来切换到处理Mix GC的增量模式。如果未达到暂停时间目标,则停止对可选部分的垃圾收集。
此功能的主要目标是改进G1垃圾收集器,以便在不活动时将Java堆内存归还给操作系统。 为实现此目标,G1将在低应用程序活动期间定期生成或持续循环检查完整的Java堆使用情况。
这将立即归还未使用的部分Java堆内存给操作系统。 用户可以选择执行FULL GC以最大化返回的内存量。
Java 12将只有一个ARM 64位实现(aarch64)。 目标是删除所有与arm64实现相关的代码,同时保留32位ARM端口和64位aarch64实现。
这将把重点转移到单个64位ARM实现,并消除维护两个实现所需的重复工作。 当前的JDK 11实现中有两个64位ARM实现。
————————————————
版权声明:本文为CSDN博主「Carry-wws」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/oldshaui/article/details/88684158
https://www.toutiao.com/a6739051172755145228/?tt_from=copy_link&utm_campaign=client_share&app=news_article%C3%97tamp%3D1569063274&utm_source=copy_link&utm_medium=toutiao_ios&req_id=201909211854330100260772061A2F0EC8&group_id=6739051172755145228
https://mp.weixin.qq.com/s?__biz=MjM5NzMyMjAwMA==&mid=2651486572&idx=1&sn=43be9e36a2c2ede54a5dcfb664ea72fc&chksm=bd2515138a529c0585f892e94c1091d7233e873a36453dad2c275ce208f7ca7caa654cde0ef1&scene=126&sessionid=1583907548&key=1de96bf14ac83757feebe979910bff485accd891c6f40ef919360c7e5c0c93fc74fde78591b2f69a36ae6c73ed29f6e8ecb5e59cb8f1fe7373d56aed48d397ba90fc1efdef27874be4bef6ef03e01063&ascene=1&uin=MTQ3MTQ0Nzk4NA%3D%3D&devicetype=Windows+10&version=62080079&lang=zh_CN&exportkey=AUt9j5VI7qRVaqs%2BtYYHCQ8%3D&pass_ticket=onhS0fnoF3IkqOw4YohwWxS6X7SPhIQfCW%2Fk8jpKEJ0mqwrUaSEc7O6Af3nDsDo4
-----------------------
来源:https://www.cnblogs.com/wynjauu/articles/10113008.html