写点什么

JDK 的前世今生:细数 Java5 - 15 的那些经典特性,java 高级程序员的要求

用户头像
Java高工P7
关注
发布于: 12 分钟前

<singer name='eason' age='10'></singer>


</list>ENDDOCUMENT

6. Common Annotations

?



Common annotations 原本是 Java EE 5.0(JSR 244)规范的一部分,现在 SUN 把它的一部分放到了 Java SE 6.0 中。随着 Annotation 元数据功能加入到 Java SE 5.0 里面,很多 Java 技术都会用 Annotation 部分代替 XML 文件来配置运行参数。



?


以下列举 Common Annotations 1.0 里面的几个 Annotations:


  • @Generated:用于标注生成的源代码

  • @Resource: 用于标注所依赖的资源,容器据此注入外部资源依赖,有基于字段的注入和基于 setter 方法的注入两种方式 。

  • @Resources:同时标注多个外部依赖,容器会把所有这些外部依赖注入

  • @PostConstruct:标注当容器注入所有依赖之后运行的方法,用来进行依赖注入后的初始化工作,只有一个方法可以标注为 PostConstruct 。

  • @PreDestroy:当对象实例将要被从容器当中删掉之前,要执行的回调方法要标注为 PreDestroy

7. Compiler API

javac 编译器可以把.java 的源文件编译为.class 文件,JDK 6 的新特性 Compiler API(JSR 199)也可以动态编译 Java 源文件。


public class CompilerApiTest {


public static void main(String[] args) throws Exception {


JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();


StandardJavaFileManager standardJavaFileManager = javaCompiler.getStandardFileManager(null,null,null);


Iterable<? extends JavaFileObject> javaFileObjects = standardJavaFileManager.getJavaFileObjects("C:\Singer.java");


javaCompiler.getTask(null, standardJavaFileManager, null, null, null, javaFileObjects).call();


standardJavaFileManager.close();


}


}


运行结果:会在 C 目录生成 Singer.class 文件

8. 对脚本语言的支持(如: ruby, groovy, javascript)

JDK6 增加了对脚本语言的支持(JSR 223),原理是将脚本语言编译成字节码,这样脚本语言也能享用 Java 平台的诸多优势,包括可移植性,安全等。JDK6 实现包含了一个基于 Mozilla Rhino 的 脚本语言引擎,因此可以支持 javascript,当然 JDK 也支持 ruby 等其他语言


public class JavaScriptTest {


public static void main(String[] args) throws Exception {


ScriptEngineManager factory = new ScriptEngineManager();


ScriptEngine engine = factory.getEngineByName("JavaScript");


String script;


try {


script = "print('Hello')";


engine.eval(script);// 执行脚本


}catch (Exception e) {


e.printStackTrace();


}


}


}


//output


Hello

Java 7 新特性

1.switch 支持 String 字符串类型。

String singer = "jay";


switch (singer) {


case "jay" :


System.out.println("周杰伦");


break;


case "eason" :


System.out.println("陈奕迅");


break ;


default :


System.out.println("其他");


break ;


}

2.try-with-resources,资源自动关闭

JDK 7 之前:


BufferedReader br = new BufferedReader(new FileReader("d:七里香.txt"));


try {


return br.readLine();


} finally {


br.close();


}


JDK 7 之后:


/*


  • 声明在 try 括号中的对象称为资源,在方法执行完毕后会被自动关闭


*/


try (BufferedReader br = new BufferedReader(new FileReader("d:七里香.txt")) {


return br.readLine();


}

3. 整数类型如(byte,short,int,long)能够用二进制来表示

//0b 或者 0B 表示二进制


int a = 0b010;


int b = 0B010;

4. 数字常量支持下划线

int a = 11_11;//a 的值为 1111,下划线不影响实际值,提升可读性

5. 泛型实例化类型自动推断,即”<>”

JDK 7 之前:


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


JDK 7 之后:


//不须声明类型,自动根据前面<>推断其类型


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

6.一个 catch 中捕获多个异常类型,用(|)分隔开

JDK 7 之前


try{


//do something


} catch (FirstException e) {


logger.error(e);


} catch (SecondException e) {


logger.error(ex);


}


JDk 7 之后


try{


//do something


} catch (FirstException | SecondException e) {


logger.error(e);


}

7. 增强的文件系统

Java7 提供了全新的 NIO2.0 API,方便文件管理的编码。如,可以在 java.nio.file 包下使用 Path、Paths、Files、WatchService 等常用类型。


Path path = Paths.get("C:\jay\七里香.txt"); //创建 Path 对象


byte[] bytes= Files.readAllBytes(path); //读取文件


System.out.println(path.getFileName()); //获取当前文件名称


System.out.println(path.toAbsolutePath()); // 获取文件绝对路径


System.out.println(new String(bytes, "utf-8"));

8. Fork/join 框架

Java7 提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。



Fork/join 计算 1-1000 累加值:


public class ForkJoinPoolTest {


private static final Integer DURATION_VALUE = 100;


static class ForkJoinSubTask extends RecursiveTask<Integer>{


// 子任务开始计算的值


private Integer startValue;


// 子任务结束计算的值


private Integer endValue;


private ForkJoinSubTask(Integer startValue , Integer endValue) {


this.startValue = startValue;


this.endValue = endValue;


}


@Override


protected Integer compute() {


//小于一定值 DURATION,才开始计算


if(endValue - startValue < DURATION_VALUE) {


System.out.println("执行子任务计算:开始值 = " + startValue + ";结束值 = " + endValue);


Integer totalValue = 0;


for (int index = this.startValue; index <= this.endValue; index++) {


totalValue += index;


}


return totalValue;


} else {


// 将任务拆分,拆分成两个任务


ForkJoinSubTask subTask1 = new ForkJoinSubTask(startValue, (startValue + endValue) / 2);


subTask1.fork();


ForkJoinSubTask subTask2 = new ForkJoinSubTask((startValue + endValue) / 2 + 1 , endValue);


subTask2.fork();


return subTask1.join() + subTask2.join();


}


}


}


public static void main(String[] args) throws ExecutionException, InterruptedException {


// Fork/Join 框架的线程池


ForkJoinPool pool = new ForkJoinPool();


ForkJoinTask<Integer> taskFuture = pool.submit(new ForkJoinSubTask(1,1000));


Integer result = taskFuture.get();


System.out.println("累加结果是:" + result);


}


}


运行结果:


...


执行子任务计算:开始值 = 189;结束值 = 250


执行子任务计算:开始值 = 251;结束值 = 313


执行子任务计算:开始值 = 314;结束值 = 375


执行子任务计算:开始值 = 376;结束值 = 438


执行子任务计算:开始值 = 439;结束值 = 500


执行子任务计算:开始值 = 501;结束值 = 563


执行子任务计算:开始值 = 564;结束值 = 625


执行子任务计算:开始值 = 626;结束值 = 688


执行子任务计算:开始值 = 689;结束值 = 750


执行子任务计算:开始值 = 751;结束值 = 813


执行子任务计算:开始值 = 814;结束值 = 875


执行子任务计算:开始值 = 876;结束值 = 938


执行子任务计算:开始值 = 939;结束值 = 1000


累加结果是:500500

Java 8 新特性

1.lambada 表达式

Lambda 允许把函数作为一个方法的参数,传递到方法中


语法格式:


(parameters) -> expression 或 (parameters) ->{ statements; }


代码示例:


Arrays.asList("jay", "Eason", "SHE").forEach(


( String singer ) -> System.out.print( singer + ",") );

2. 函数式接口

Lambda 的设计者为了让现有的功能与 Lambda 表达式很好兼容,设计出函数式接口。


  • 函数式接口是指只有一个函数的接口,可以隐式转换为 lambada 表达式。

  • Java 8 提供了注解 @FunctionalInterface,显示声明一个函数式接口。

  • java.lang.Runnable 和 java.util.concurrent.Callable 是函数式接口的例子~


@FunctionalInterface


public interface Runnable {


public abstract void run();


}

3. 方法引用

方法引用提供了非常有用的语法,可以直接引用已有 Java 类或对象(实例)的方法或构造器。它与 Lambda 表达式配合使用,可以减少冗余代码,使代码更加简洁。


//利用函数式接口 Consumer 的 accept 方法实现打印,Lambda 表达式如下


Consumer<String> consumer = x -> System.out.println(x);


consumer.accept("jay");


//引用 PrintStream 类(也就是 System.out 的类型)的 println 方法,这就是方法引用


consumer = System.out::println;


consumer.accept("私信资料,领一线大厂面试专题");

4. 默认方法

默认方法就是一个在接口里面有了一个实现的方法。它允许将新方法添加到接口,但不强制实现了该接口的类必须实现新的方法。


public interface ISingerService {


// 默认方法


default void sing(){


System.out.println("唱歌");


}


void writeSong();


}


//JaySingerServiceImpl 不用强制实现 ISingerService 的默认 sing()方法


public class JaySingerServiceImpl implements ISingerService {


@Override


public void writeSong() {


System.out.println("写了一首七里香");


}


}

5.Stream API

Stream API,支持对元素流进行函数式操作,它集成在 Collections API 中,可以对集合进行批量操作。常用 API:


  • filter 筛选

  • map 流映射

  • reduce 将流中的元素组合起来

  • collect 返回集合

  • sorted 排序

  • flatMap 流转换

  • limit 返回指定流个数

  • distinct 去除重复元素


public class Singer {


private String name;


private Integer songNum;


private Integer age;


...


}


List<Singer> singerList = new ArrayList<Singer>();


singerList.add(new Singer("jay", 11, 36));


singerList.add(new Singer("eason", 8, 31));


singerList.add(new Singer("JJ", 6, 29));


List<String> singerNameList = singerList.stream()


.filter(singer -> singer.getAge() > 30) //筛选年龄大于 30


.sorted(Comparator.comparing(Singer::getSongNum)) //根据歌曲数量排序


.map(Singer::getName) //提取歌手名字


.collect(Collectors.toList()); //转换为 List

6. Optional

Java 8 引入 Optional 类,用来解决 NullPointerException。Optional 代替 if…else 解决空指针问题,使代码更加简洁。


if…else 判空


Singer singer = getSingerById("666");


if (singer != null) {


String name = singer.getName();


System.out.println(name);


}


Optional 的判空


Optional<Singer> singer = Optional.ofNullable(getSingerById("666"));


singer.ifPresent(s -> System.out.println(s.getName()));

7. Date Time API

JDK 8 之前的日期 API 处理存在非线程安全、时区处理麻烦等问题。Java 8 在 java.time 包下提供了新的日期 API,简化了日期的处理~


LocalDate today = LocalDate.now();


int year = today.getYear();


System.out.println("今年是" + year);


//是否闰年


System.out.println("今年是不是闰年:" + today.isLeapYear());


LocalDateTime todayTime = LocalDateTime.now();


System.out.println("当前时间" + todayTime);


//时区指定


System.out.println("美国时间:" + ZonedDateTime.of(todayTime,ZoneId.of("America/Los_Angeles")));


LocalDate specailDate = LocalDate.of(2020, 6, 20);


LocalDate expectDate = specailDate.plus(100, ChronoUnit.DAYS);


System.out.println("比较特别的一天" + specailDate);


System.out.println("特殊日期的 100 天" + expectDate);

8. 重复注解

重复注解,即一个注解可以在一个类、属性或者方法上同时使用多次;用 @Repeatable 定义重复注解


@Repeatable(ScheduleTimes.class)


public @interface ScheduleTime {


String value();


}


public @interface ScheduleTimes {


ScheduleTime[] value();


}


public class ScheduleTimeTask {


@ScheduleTime("10")


@ScheduleTime("12")


public void doSomething() { }


}

9. Base64

Java 8 把 Base64 编码的支持加入到官方库中~


String str = "私信资料,领一线大厂面试专题";


String encoded = Base64.getEncoder().encodeToString(str.getBytes( StandardCharsets.UTF_8));


String decoded = new String(Base64.getDecoder().decode(encoded), StandardCharsets.UTF_8);

10. JVM 的新特性

使用元空间 Metaspace 代替持久代(PermGen space),JVM 参数使用-XX:MetaSpaceSize 和-XX:MaxMetaspaceSize 设置大小。

Java 9 新特性

1. java 模块系统

什么是模块化?


?



一个大型系统,比如一个商城网站,它会包含很多模块的,如:订单模块,用户信息模块,商品信息模块,广告位模块等等。各个模块之间会相互调用。如果每个模块单独运行都会带动其他所有模块,性能非常低效。但是,如果某一模块运行时,只会启动它所依赖的模块,性能大大提升。这就是 JDK 9 模块化的思想。



?


什么是 JDK 9 模块化?


?



Java 平台模块系统,即 Project Jigsaw,把模块化开发实践引入到了 Java 平台中。在引入了模块系统之后,JDK 被重新组织成 94 个模块。Java 应用可以通过新增的 jlink 工具,创建出只包含所依赖的 JDK 模块的自定义运行时镜像。这样可以极大的减少 Java 运行时环境的大小。



?


Java 9 模块的重要特征:


?



  • 在其工件(artifact)的根目录中包含了一个描述模块的 module-info.cla


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


ss 文 件。


  • 工件的格式可以是传统的 JAR 文件或是 Java 9 新增的 JMOD 文件。


  • 这个文件由根目录中的源代码文件 module-info.java 编译而来。


  • 该模块声明文件可以描述模块的不同特征。



?


在 module-info.java 文件中,我们可以用新的关键词 module 来声明一个模块,如下所示。下面给出了一个模块 com.mycompany.mymodule 的最基本的模块声明


module com.jay.sample { //关键词 module 来声明一个模块


exports com.jay.sample; //使用 exports 可以声明模块对其他模块所导出的包。


requires com.jay.common; //使用 requires 可以声明模块对其他模块的依赖关系。


}

2. 不可变集合工厂方法

为了创建不可变集合,JDK9 之前酱紫的:


List<String> stringList = new ArrayList<>();


stringList.add("私信资料:");


stringList.add("领一线大厂面试专题");


List<String> unmodifiableList = Collections.unmodifiableList(stringList);


JDK 9 提供了 List.of()、Set.of()、Map.of()和 Map.ofEntries()等工厂方法来创建不可变集合:


List<String> unmodifiableList = List.of("私信资料:","领一线大厂面试专题");

3. 接口支持私有方法

JDK 8 支持在接口实现默认方法和静态方法,但是不能在接口中创建私有方法,为了避免了代码冗余和提高阅读性,JDK 9 在接口中支持私有方法。


public interface IPrivateInterfaceTest {


//JDK 7 之前


String a = "jay";


void method7();


//JDK 8


default void methodDefault8(){


System.out.println("JDK 8 新特性默认方法");


}


static void methodStatic8() {


System.out.println("JDk 8 新特性静态方法");


}


//Java 9 接口支持私有方法


private void method9(){}


}

4. ?钻石操作符升级

  • 钻石操作符是在 java 7 中引入的,可以让代码更易读,但它不能用于匿名的内部类。

  • 在 java 9 中, 它可以与匿名的内部类一起使用,从而提高代码的可读性。


//JDK 5,6


Map<String, String> map56 = new HashMap<String,String>();


//JDk 7,8


Map<String, String> map78 = new HashMap<>();


//JDK 9 结合匿名内部类的实现


Map<String, String> map9 = new HashMap<>(){};

5. Optional 类改进

java 9 中,java.util.Optional 添加了很多新的有用方法,如:


  • stream()

  • ifPresentOrElse()

  • or()


ifPresentOrElse 方法的改进就是有了 else,接受两个参数 Consumer 和 Runnable。


import java.util.Optional;


public class OptionalTest {


public static void main(String[] args) {


Optional<Integer> optional = Optional.of(1);


optional.ifPresentOrElse( x -> System.out.println("Value: " + x),() ->


System.out.println("Not Present."));


optional = Optional.empty();


optional.ifPresentOrElse( x -> System.out.println("Value: " + x),() ->


System.out.println("Not Present."));


}


}

6. 多版本兼容 Jar 包

?



很多公司使用的 JDK 都是老版本的,JDK6、JDk5 ,甚至 JDk4 的,不是他们不想升级 JDk 版本,而是担心兼容性问题。JDK 9 的一个新特性,多版本兼容 Jar 包解决了这个问题。举个例子:假设你一直用的是小米 8,已经非常习惯它的运行流程了,突然出来小米 9,即使小米 9 很多新功能引人入胜,但是有些人不会轻易买小米 9,因为已经已经习惯小米 8 的流程。同理,为什么很多公司不升级 JDK,就是在此。但是呢,JDK 9 的这个功能很强大,它可以让你的版本升级到 JDK 9,但是还是老版本的运行流程,即在老的运行流程继承新的功能~



?

7. JShell 工具

jShell 工具相当于 cmd 工具,然后呢,你可以像在 cmd 工具操作一样,直接在上面运行 Java 方法,Java 语句等~


jshell> System.out.println("私信资料,领一线大厂面试专题");


私信资料,领一线大厂面试专题

8. try-with-resources 的改进

JDK 9 对 try-with-resources 异常处理机制进行了升级~


//JDK 7,8


try (BufferedReader br = new BufferedReader(new FileReader("d:七里香.txt")) {


br.readLine();


}catch(IOException e){


log.error("IO 异常,e:{}",e);


}


//JDk 9


BufferedReader br = new BufferedReader(new FileReader("d:七里香.txt")


try(br){


br.readLine();


}catch(IOException e){


log.error("IO 异常,e:{}",e);


}

9. Stream API 的改进

JDK 9 为 Stream API 引入以下这些方法,丰富了流处理操作:


  • takeWhile()

  • dropWhile()

  • iterate

  • ofNullable


「takeWhile」


使用一个断言(Predicate 接口)作为参数,返回给定 Stream 的子集直到断言语句第一次返回 false


// 语法格式


default Stream<T> takeWhile(Predicate<? super T> predicate)


//代码示例


Stream.of(1,2,3).takeWhile(s-> x<2)


.forEach(System.out::println);


//输出


1


「dropWhile」


与 takeWhile()作用相反,使用一个断言(Predicate 接口)作为参数,直到断言语句第一次返回 true,返回给定 Stream 的子集


//语法


default Stream<T> dropWhile(Predicate<? super T> predicate)


//代码示例


Stream.of(1,2,3).dropWhile(s-> x<2)


.forEach(System.out::println);


//输出


2


3


「iterate」


iterate() 方法能够返回以 seed(第一个参数)开头,匹配 Predicate(第二个参数)直到返回 false,并使用第三个参数生成下一个元素的元素流。


//语法


static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next)


//代码示例


IntStream.iterate(2, x -> x < 10, x -> x*x).forEach(System.out::println);


//输出


2


4


「ofNullable」


如果指定元素为非 null,则获取一个元素并生成单个元素流,元素为 null 则返回一个空 Stream。


//语法


static <T> Stream<T> ofNullable(T t)


//代码示例


Stream<Integer> s1= Stream.ofNullable(100);


s1.forEach(System.out::println)


Stream<Integer> s2 = Stream.ofNullable(null);


s2.forEach(System.out::println)


//输出


100

10.其他

?



  • HTTP 2 客户端 (支持 WebSocket 和 HTTP2 流以及服务器推送)


  • 进程 API(控制和管理操作系统进程)


  • String 底层存储结构更改(char[]替换为 byte[])


  • 标识符添加限制( String _ ="hello"不能用)


  • 响应式流 API (支持 Java 9 中的响应式编程)



?

Java 10 新特性

1.局部变量类型推断

JDK 10 增加了局部变量类型推断(Local-Variable Type Inference)功能,让 Java 可以像 Js 里的 var 一样可以自动推断数据类型。Java 中的 var 是一个保留类型名称,而不是关键字。


JDK 10 之前


List<String> list = new ArrayList<String>();


Stream<Integer> stream = Stream.of(1, 2, 3);


JDK 10 之后


var list = new ArrayList<String>(); // ArrayList<String>


var stream = Stream.of(1, 2, 3);


var 变量类型推断的使用也有局限性,仅**「局限」**于以下场景:


  • 具有初始化器的局部变量

  • 增强型 for 循环中的索引变量

  • 传统 for 循环中声明的局部变量


而**「不能用于」**


  • 推断方法的参数类型

  • 构造函数参数类型推断

  • 推断方法返回类型

  • 字段类型推断

  • 捕获表达式

2. 不可变集合的改进

JDK 10 中,List,Set,Map 提供了一个新的静态方法 copyOf(Collection<? extends E> coll),它返回 Collection 集合一个不可修改的副本。


JDK 源码:


static <E> List<E> copyOf(Collection<? extends E> coll) {


return ImmutableCollections.listCopy(coll);


}


使用实例:


var oldList = new ArrayList<String>();


oldList.add("私信资料:");


oldList.add("");


var copyList = List.copyOf(oldList);


oldList.add("收藏、转载、点赞三连");


copyList.add("双击 666"); //UnsupportedOperationException 异常

3. 并行全垃圾回收器 G1

?



JDK 9 引入 G1 作为默认垃圾收集器,执行 GC 时采用的是基于单线程标记扫描压缩算法(mark-sweep-compact)。为了最大限度地减少 Full GC 造成的应用停顿的影响,Java 10 中将为 G1 引入多线程并行 GC,同时会使用与年轻代回收和混合回收相同的并行工作线程数量,从而减少了 Full GC 的发生,以带来更好的性能提升、更大的吞吐量。



?

4. 线程本地握手

Java 10 中线程管控引入 JVM 安全点的概念,将允许在不运行全局 JVM 安全点的情况下实现线程回调,由线程本身或者 JVM 线程来执行,同时保持线程处于阻塞状态,这将会很方便使得停止单个线程或不停止线程成为可能。

5. Optional 新增 orElseThrow()方法

Optional、OptionalDouble 等类新增一个方法 orElseThrow(),在没有值时抛出异常

6. 其他新特性

  • 基于 Java 的 实验性 JIT 编译器

  • 类数据共享

  • Unicode 语言标签扩展

  • 根证书

  • 基于时间(Time-Based)的版本控制模型

Java 11 新特性

1.字符串操作

String 类是 Java 最常用的类,JDK 11 增加了一系列好用的字符串处理方法


  • isBlank() 判空。

  • strip() 去除首尾空格

  • stripLeading() 去除字符串首部空格

  • stripTrailing() 去除字符串尾部空格

  • lines() 分割获取字符串流。

  • repeat() 复制字符串


// 判断字符串是否为空白


" ".isBlank(); // true


// 去除首尾空格


" jay ".strip(); // "jay"


// 去除首部空格


" jay ".stripLeading(); // "jay "


去除字符串尾部空格


" jay ".stripLeading(); // " jay"


// 行数统计


"a\nb\nc".lines().count(); // 3


// 复制字符串


"jay".repeat(3); // "jayjayjay"

2.用于 Lambda 参数的局部变量语法

局部变量类型推断是 Java 10 引入的新特性,但是不能在 Lambda 表达式中使用。Java 11 再次创新,它允许开发者在 Lambda 表达式中使用 var 进行参数声明。


var map = new HashMap<String, Object>();


map.put("私信资料", "领一线大厂面试专题");


map.forEach((var k, var v) -> {


System.out.println(k + ": " + v);


});

3.标准化 HTTP Client

Java 9 引入 Http Client API,Java 10 对它更新,Java 11 对它进行标准化。这几个版本后,Http Client 几乎被完全重写,支持 HTTP/1.1 和 HTTP/2 ,也支持 websockets。


HttpClient client = HttpClient.newHttpClient();


HttpRequest request = HttpRequest.newBuilder()


.uri(URI.create("https://github.com/whx123/JavaHome"))


.GET()


.build();


// 同步


HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());


System.out.println(response.body());


// 异步


client.sendAsync(request, HttpResponse.BodyHandlers.ofString())


.thenApply(HttpResponse::body)


.thenAccept(System.out::println);

4. 单个命令编译运行源代码

Java 11 增强了 Java 启动器,使之能够运行单一文件的 Java 源代码。


  • Java 11 之前,要运行一个 Java 源代码必须先编译,再运行


// 编译


javac Jay.java


// 运行


java Jay


  • Java 11 之后,只要一个 java 命令就搞定


java Jay.java

5. ZGC:可伸缩低延迟垃圾收集器

ZGC ,即 Z Garbage Collector(垃圾收集器或垃圾回收器)。它是一个可伸缩的、低延迟的垃圾收集器。 ZGC 主要为了满足如下目标进行设计:


  • GC 停顿时间不超过 10ms

  • 既能处理几百 MB 的小堆,也能处理几个 TB 的大堆

  • 应用吞吐能力不会下降超过 15%(与 G1 回收算法相比)

  • 方便在此基础上引入新的 GC 特性和利用 colord

  • 针以及 Load barriers 优化奠定基础

  • 当前只支持 Linux/x64 位平台

6.其他一些特性

  • 添加 Epsilon 垃圾收集器。

  • 支持 TLS 1.3 协议

  • 飞行记录器分析工具

  • 动态类文件常量

  • 低开销的 Heap Profiling

Java 12 新特性

1. Switch 表达式扩展(预览功能)

传统的 switch 语句,容易漏写 break 而出错,同时写法并不简洁优雅。


Java 12 之前


switch (day) {


case MONDAY:


case FRIDAY:


case SUNDAY:


System.out.println(6);


break;


case TUESDAY:


System.out.println(7);


break;


case THURSDAY:


case SATURDAY:


System.out.println(8);


break;


case WEDNESDAY:


System.out.println(9);


break;


}


JDk 12 之后,Switch 表达式得到增强,能接受语句和表达式。


switch (day) {


case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);


case TUESDAY -> System.out.println(7);


case THURSDAY, SATURDAY -> System.out.println(8);


case WEDNESDAY -> System.out.println(9);


}

2. 紧凑的数据格式

JDK 12 新增了 NumberFormat 对复杂数字的格式化


NumberFormat numberFormat = NumberFormat.getCompactNumberInstance(Locale.CHINA, NumberFormat.Style.SHORT);


System.out.println(numberFormat.format(100000));


//output


10 万

3. 字符串支持 transform、indent 操作

  • transform 字符串转换,可以配合函数式接口 Function 一起使用


List<String> list1 = List.of("jay", " 私信资料,领一线大厂面试专题");


List<String> list2 = new ArrayList<>();


list1.forEach(element ->


list2.add(element.transform(String::strip)


.transform((e) -> "Hello," + e))


);


list2.forEach(System.out::println);


//输出


Hello,jay


Hello,私信资料,领一线大厂面试专题


  • indent 缩进,每行开头增加空格 space 和移除空格


String result = "Java\n Python\nC".indent(3);


System.out.println(result);


//输出


Java


Python


C

4. Files.mismatch(Path, Path)

Java 12 新增了 mismatch 方法,此方法返回第一个不匹配的位置,如果没有不匹配,则返回 -1L。


public static long mismatch(Path path, Path path2) throws IOException;


代码示例:


Path file1 = Paths.get("c:\jay.txt");


Path file2 = Paths.get("c:\私信资料领一线大厂面试专题.txt");


try {


long fileMismatch = Files.mismatch(file1, file2);


System.out.println(fileMismatch);


} catch (IOException e) {


e.printStackTrace();


}

5. Teeing Collector

Teeing Collector 是 Streams API 中引入的新的收集器实用程序,它的作用是 merge 两个 collector 的结果,API 格式如下:


public static <T, R1, R2, R>


Collector<T, ?, R> teeing(Collector<? super T, ?, R1> downstream1,


Collector<? super T, ?, R2> downstream2,


BiFunction<? super R1, ? super R2, R> merger)


直接看代码例子吧,如下为求学生的平均分和总分的例子


List<Student> studentList= Arrays.asList(


new Student("jay", 90),


new Student("私信资料,领一线大厂面试专题", 100),


new Student("私信资料,领一线大厂面试专题", 80)


);


String teeingResult=studentList.stream().collect(


Collectors.teeing(


Collectors.averagingInt(Student::getScore),


Collectors.summingInt(Student::getScore),


(s1,s2)-> s1+ ":"+ s2


)


);


System.out.println(teeingResult); //90:270

6.其他特性

  • 支持 unicode 11(684 个新字符、11 个新 blocks、7 个新脚本)

  • JVM 常量 API (主要在新的 java.lang.invoke.constant 包中定义了一系列基于值的符号引用类型,能够描述每种可加载常量。)

  • Shenandoah GC(低暂停时间垃圾收集器)

  • G1 收集器提升 (可中止的混合收集集合、及时返回未使用的已分配内存)

  • 默认 CDS 档案

  • JMH 基准测试

Java 13 新特性

Switch 表达式扩展(引入 yield 关键字)

传统的 switch:


private static String getText(int number) {


String result = "";


switch (number) {


case 1, 2:


result = "one or two";


break;


case 3:


result = "three";


break;


case 4, 5, 6:


result = "four or five or six";


break;


default:


result = "unknown";


break;


Java 13 之后,value break 语句不再被编译,而是用 yield 来进行值返回


private static String getText(int number) {


return switch (number) {


case 1, 2:


yield "one or two";


case 3:


yield "three";


case 4, 5, 6:


yield "four or five or six";


default:


yield "unknown";


};


}

2.文本块升级

Java 13 之前,字符串不能够多行使用,需要通过换行转义或者换行连接符等等,反正就是好麻烦、好难维护。


String html = "<html>\n" +


" <body>\n" +


" <p>Hello, 私信资料,领一线大厂面试专题</p>\n" +


" </body>\n" +


"</html>\n";


Java 13 之后,清爽多了~


String html = """


<html>


<body>


<p>Hello, 私信资料,领一线大厂面试专题</p>


</body>


</html>


""";

3. SocketAPI 重构

  • 传统的 Java Socket API(java.net.ServerSocket 和 java.net.Socket)依赖于 SocketImpl 的内部实现

  • 在 Java 13 之前,通过使用 PlainSocketImpl 作为 SocketImpl 的具体实现。

  • Java 13 中的新底层实现,引入 NioSocketImpl 的实现用以替换 SocketImpl 的 PlainSocketImpl 实现,此实现与 NIO(新 I/O)实现共享相同的内部基础结构,并且与现有的缓冲区高速缓存机制集成在一起。


一个 Socket 简单例子:


import java.io.IOException;


import java.net.ServerSocket;


import java.net.Socket;


public class SocketAPITest {


public static void main(String[] args) {


try (ServerSocket serverSocket = new ServerSocket(8080)){


boolean runFlag = true;


while(runFlag){


Socket clientSocket = serverSocket.accept();


//搞事情


}


} catch (IOException e) {


e.printStackTrace();


}


}


}


运行以上的实例,看下是否有以下关键词输出~


[class,load] sun.nio.ch.NioSocketImpl

4.FileSystems.newFileSystem 新方法

FileSystems 类中添加了以下三种新方法,以便更容易地使用将文件内容视为文件系统的文件系统提供程序:


  • 1、newFileSystem(Path)

  • 2、newFileSystem(Path, Map<String, ?>)

  • 3、newFileSystem(Path, Map<String, ?>, ClassLoader)

5. 增强 ZGC 释放未使用内存

  • ZGC 是 Java 11 中引入的最为瞩目的垃圾回收特性,是一种可伸缩、低延迟的垃圾收集器。但是实际使用中,它不能够主动将未使用的内存释放给操作系统。

用户头像

Java高工P7

关注

还未添加个人签名 2021.11.08 加入

还未添加个人简介

评论

发布
暂无评论
JDK的前世今生:细数 Java5 - 15 的那些经典特性,java高级程序员的要求