乐趣区

关于java:Java程序员必备基础JDK-515都有哪些经典新特性

前言

JDK 15 公布啦~ 咱们一起回顾 JDK 5-15 的新个性吧,大家一起学习哈~

本文曾经收录到 github

https://github.com/whx123/Jav…

公众号:捡田螺的小男孩

Java 5 新个性

1. 泛型

泛型实质是参数化类型,解决不确定具体对象类型的问题。

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

2. 加强循环(for-each)

for-each 循环简化了汇合的遍历。

String [] str = {"关注","公众号","捡田螺的小男孩"};
for (String temp:str) {System.out.println(temp);
}

3. 主动封箱拆箱

  • 主动装箱: 就是将根本数据类型主动转换成对应的包装类。
  • 主动拆箱:就是将包装类主动转换成对应的根本数据类型。

包装类型有:Integer,Double,Float,Long,Short,Character 和 Boolean

Integer i =666;  // 主动装箱
int a= i;     // 主动拆箱

4. 枚举

关键字 enum 能够将一组具名的值的无限汇合创立为一种新的类型,而这些具名的值能够作为惯例的程序组件应用,这就是枚举类型。

enum SeasonEnum {SPRING,SUMMER,FALL,WINTER;}

5. 可变参数

咱们在定义方法参数的时候不确定定义多少个,就能够定义为 可变参数 ,它实质上是一个 数组

public static void main(String[] args) throws Exception {String [] str = {"关注","公众号","捡田螺的小男孩"};
    testVarargs(str);
    String str1 = "关注公众号,捡田螺的小男孩";
    testVarargs(str1);
}
// 可变参数 String... args
private static void testVarargs(String... args) {for (String arg : args) {System.out.println(arg);
    }
}

6. 注解

能够把注解了解为代码里的非凡标记,这些标记能够在编译,类加载,运行时被读取,并执行相应的解决。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {}

7. 动态导入

通过 import static 类,就能够应用类里的动态变量或办法。看一下例子哈~

import static java.lang.System.out; // 动态导入 System 类的动态变量 out
public class Test {public static void main(String[] args) throws Exception {
        String str1 = "关注公众号,捡田螺的小男孩";
        System.out.println(str1); // 惯例写法
        out.println(str1);  // 动态导入,能够间接应用 out 输入
    }
}

8. 线程并发库(JUC)

JDK5 丰盛了线程解决性能,java.util.concurrent 包提供了以下的类、接口:

  • 线程池:ExecutorService 接口
  • 线程护斥:Lock 类
  • 线程通信:Condition 接口
  • 同步队列:ArrayBlockingQueue 类
  • 同步汇合:ConcurrentHashMap 类

Java 6 新个性

1.Desktop 类和 SystemTray 类

JDK 6 在 java.awt 包下,新增了两个类:Desktop 类和 SystemTray 类

  • Desktop 类: 用来关上零碎默认浏览器浏览指定的 URL, 关上零碎默认邮件客户端发邮件等
  • SystemTray 类: 用来在系统托盘区创立一个托盘程序, 如果在微软的 Windows 上,它被称为“任务栏”状态区域。
// 获取 Desktop 实例
Desktop desktop = Desktop.getDesktop();
desktop.browse(URI.create("https://www.baidu.com"));

2. 应用 JAXB2 来实现对象与 XML 之间的映射

JAXB, 即 Java Architecture for XML Binding, 能够实现对象与 XML 之间的映射,罕用注解如下:

  • @XmlRootElement:注解在类下面,对应 xml 的跟元素,应用 name 属性定义根节点的名称。
  • @XmlElement:指定一个字段或 get/set 办法映射到 xml 的节点,应用 name 属性定义这个根节点的名称。
  • @XmlAttribute:将 JavaBean 对象的属性映射为 xml 的属性, 应用 name 属性为生成的 xml 属性指定别名。
  • @XmlAccessorType: 定义映射这个类中的何种类型都须要映射到 xml。
  • @XmlSchema: 将包映射到 XML 名称空间

看个例子吧~

public class JAXB2XmlTest {public static void main(String[] args) throws JAXBException, IOException {List<Singer> list = new ArrayList<>();
        list.add(new Singer("jay", 8));
        list.add(new Singer("eason", 10));

        SingerList singerList = new SingerList();
        singerList.setSingers(list);

        String str = JAXB2XmlTest.beanToXml(singerList, SingerList.class);
        String path = "C:\\jay.txt";
        BufferedWriter bfw = new BufferedWriter(new FileWriter(new File(path)));
        bfw.write(str);
        bfw.close();}

    private static String beanToXml(Object obj, Class<?> load) throws JAXBException {JAXBContext context = JAXBContext.newInstance(load);
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "GBK");
        StringWriter writer = new StringWriter();
        marshaller.marshal(obj,writer);
        return writer.toString();}
}
public class Singer {

    private String name;
    private int age;
    public Singer(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @XmlAttribute(name="name")
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    @XmlAttribute(name="age")
    public int getAge() {return age;}
    public void setAge(int age) {this.age = age;}
}
@XmlRootElement(name="list")
public class SingerList {

    private List<Singer> singers;
    
    @XmlElement(name="singer")
    public List<Singer> getSingers() {return singers;}

    public void setSingers(List<Singer> singers) {this.singers = singers;}
}

运行成果:

<?xml version="1.0" encoding="GBK" standalone="yes"?>
<list>
    <singer age="8" name="jay"/>
    <singer age="10" name="eason"/>
</list>

3. 轻量级 Http Server API

JDK 6 中提供了简略的 Http Server API,能够构建嵌入式 Http 服务器, 同时反对 Http 和 Https 协定。HttpServer 会调用 HttpHandler 实现类的回调办法来解决客户端申请, 这里用户只需实现 HttpHandler 接口就能够了。

/**
 * 依据 Java 提供的 API 实现 Http 服务器
 */
public class MyHttpServer {

    /**
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        // 创立 HttpServer 服务器
        HttpServer httpServer = HttpServer.create(new InetSocketAddress(8080), 10);
        // 将 /jay 申请交给 MyHandler 处理器解决
        httpServer.createContext("/", new MyHandler());
        httpServer.start();}
}

public class MyHandler implements HttpHandler {public void handle(HttpExchange httpExchange) throws IOException {
        // 申请头
        Headers headers = httpExchange.getRequestHeaders();
        Set<Map.Entry<String, List<String>>> entries = headers.entrySet();

        StringBuffer response = new StringBuffer();
        for (Map.Entry<String, List<String>> entry : entries){response.append(entry.toString() + "\n");
        }
        // 设置响应头属性及响应信息的长度
        httpExchange.sendResponseHeaders(200, response.length());
        // 取得输入流
        OutputStream os = httpExchange.getResponseBody();
        os.write(response.toString().getBytes());
        os.close();}
}

4. 插入式注解解决 API

JDK 6 提供了插入式注解解决 API,能够让咱们定义的注解在编译期而不是运行期失效,从而能够在编译期批改字节码。lombok 框架就是应用该个性来实现的,Lombok 通过注解的形式,在编译时主动为属性生成结构器、getter/setter、equals、hashcode、toString 等办法,大大简化了代码的开发。

5. STAX

STAX,是 JDK6 中一种解决 XML 文档的 API。

public class STAXTest {public static void main(String[] args) throws Exception {XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
        XMLEventReader xmlEventReader = xmlInputFactory.createXMLEventReader(new FileInputStream("C:\\jay.xml"));
        XMLEvent event = null;
        StringBuffer stringBuffer = new StringBuffer();
        while (xmlEventReader.hasNext()) {event = xmlEventReader.nextEvent();
            stringBuffer.append(event.toString());
        }
        System.out.println("xml 文档解析后果:");
        System.out.println(stringBuffer);
    }
}

运行后果:

xml 文档解析后果:<?xml version="1.0" encoding='GBK' standalone='yes'?><list>
    <singer name='jay' age='8'></singer>
    <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.class 文 件。
  • 工件的格局能够是传统的 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 13 中对 ZGC 的改良,包含开释未应用内存给操作系统、反对最大堆大小为 16TB、JVM 参数 -XX:SoftMaxHeapSize 来软限度堆大小

6. 其余个性

  • 动静 CDS 存档,扩大了 Java 10 中引入的类数据共享性能,应用 CDS 存档变得更容易。
  • 文本块的字符串类新办法,如 formatted(Object…args),stripIndent()等。

Java 14 新个性

1. instanceof 模式匹配

instanceof 传统应用形式:

if (person instanceof Singer) {Singer singer = (Singer) person;
    singer.sing();} else if (person instanceof Writer) {Writer writer = (Writer) person;
    writer.write();}

Java 14 对 instanceof 进行模式匹配改良之后

if (person instanceof Singer singer) {singer.sing();
} else if (person instanceof Writer writer) {writer.write();
}

2.Record 类型(预览性能)

Java 14 将 Record 类型作为预览个性而引入,有点相似于 Lombok 的 @Data 注解,看个例子吧:

public record Person(String name, int age) {
    public static String address;

    public String getName() {return name;}
}

反编译后果:

public final class Person extends java.lang.Record {
    private final java.lang.String name;
    private final java.lang.String age;

    public Person(java.lang.String name, java.lang.String age) {/* compiled code */}

    public java.lang.String getName() { /* compiled code */}

    public java.lang.String toString() { /* compiled code */}

    public final int hashCode() { /* compiled code */}

    public final boolean equals(java.lang.Object o) {/* compiled code */}

    public java.lang.String name() { /* compiled code */}

    public java.lang.String age() { /* compiled code */}
}

能够发现,当用 Record 来申明一个类时,该类将主动领有上面特色:

  • 构造方法
  • hashCode() 办法
  • euqals() 办法
  • toString() 办法
  • 类对象被 final 关键字润饰,不能被继承。

3. Switch 表达式 - 标准化

switch 表达式在之前的 Java 12 和 Java 13 中都是处于预览阶段,终于在 Java 14 标准化,成为稳固版本。

  • Java 12 为 switch 表达式引入 Lambda 语法
  • Java 13 应用 yield 代替 break 关键字来返回表达式的返回值。
String result = switch (day) {
    case "M", "W", "F" -> "MWF";
    case "T", "TH", "S" -> "TTS";
    default -> {if (day.isEmpty()) {yield "Please insert a valid day.";} else {yield "Looks like a Sunday.";}
    }
};
System.out.println(result);

4. 改良 NullPointerExceptions 提示信息

Java 14 之前:

String name = song.getSinger().getSingerName()
 
// 堆栈信息
Exception in thread "main" java.lang.NullPointerException
    at NullPointerExample.main(NullPointerTest.java:6)

Java 14,通过引入 JVM 参数 -XX:+ShowCodeDetailsInExceptionMessages,能够在空指针异样中获取更为具体的调用信息。

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Singer.getSingerName()" 
because the return value of "rainRow.getSinger()" is null
    at NullPointerExample.main(NullPointerTest.java:6)

5. 其余个性

  • G1 的 NUMA 可辨认内存调配
  • 删除 CMS 垃圾回收器
  • GC 反对 MacOS 和 Windows 零碎

Java 15 新个性


1.EdDSA 数字签名算法

  • 应用 Edwards-Curve 数字签名算法(EdDSA)实现加密签名。
  • 与其它签名计划相比,EdDSA 具备更高的安全性和性能。
  • 失去许多其它加密库(如 OpenSSL、BoringSSL)的反对。

2.Sealed Classes(关闭类,预览)

关闭类,能够是关闭类、关闭接口,避免其余类或接口扩大或实现它们。

public abstract sealed class Singer
    permits Jay, Eason{...}

类 Singer 被 sealed 润饰,是关闭类,只能被 2 个指定子类(Jay, Eason)继承。

3. Hidden Classes(暗藏类)

  • 暗藏类天生为框架设计的。
  • 暗藏类只能通过反射拜访,不能间接被其余类的字节码。

4. Remove the Nashorn JavaScript Engine

  • Nashorn 太难保护了,移除 Nashorn JavaScript 引擎成为一种必然
  • 其实早在 JDK 11 中就曾经被标记为 deprecated 了。

5.Reimplement the Legacy DatagramSocket API(从新实现 DatagramSocket API)

  • 从新实现老的 DatagramSocket API
  • 更改 java.net.DatagramSocket 和 java.net.MulticastSocket 为更加简略、现代化的底层实现。

6. 其余

  • Disable and Deprecate Biased Locking(筹备禁用偏差锁)
  • instanceof 主动匹配模式(预览)
  • ZGC,一个可伸缩、低提早的垃圾回收器。(转正)
  • Text Blocks,文本性能转正(JDK 13 和 14 预览,14 终于转正)
  • Remove the Solaris and SPARC Ports(删除 Solaris 和 SPARC 端口)
  • 内部存储器拜访 API(容许 Java 应用程序平安无效地拜访 Java 堆之外的内部内存。)
  • Record 类型二次预览(在 Java 14 就预览过啦)

参考与感激

  • JDK6 新个性
  • Java 7 的新性能
  • Java 9 新个性概述
  • Java 9 新个性
  • Java 10 新个性介绍
  • Java 11 新个性介绍
  • Java 13 新个性概述
  • Java 14 新个性概述
  • JDK/Java 15 公布
  • [Java 15 正式公布,14 个新个性,刷新你的认知!!

](https://www.cnblogs.com/javas…

集体公众号

退出移动版