java9新特性----大总结--建议收藏、点赞、关注 三连

文章导航:java8新特性—大总结–建议收藏、点赞、加关注!!!


一、java9目录结构的改变

java9引入模块的概念因此,目录发生了改变

java8中

在这里插入图片描述

java11中(和java 9一样的目录结构)

下面框出来的是和java8不一致的地方
在这里插入图片描述
legal是法律文件
jmods里面存的是jmod文件,创建自定义运行时的映射值就需要修改jmod文件
conf是jdk9中的配置文件

二、新特性:模块化系统

原先的名称是Jigsaw项目,后面命名为Modularity项目
以前的项目是通过包名来拆分代码,方便管理,在java9中引入模块概念
例如一个电商的项目,可以分
订单模块
支付模块
然后每一个模块相当于一个小项目,在IDEA中天然支持这种方式的项目

在这里插入图片描述
demo模块依赖java9module模块,需要使用到java9module模块中的Person
在这里插入图片描述
在项目类路径下创建一个module-info.java,对于需要暴露的则通过exports关键字+需要暴露的包名类路径

module java9module {
    
    
    exports com.example.entity;
}

demo需要使用java9modulecom.example.entity包下的Person类,则通过requires关键字引入模块

module demo {
    
    
    requires java9module;
}

然后就可以和以前一样的使用方式imports引入,正常使用
在这里插入图片描述

三、新特性 jshell 的引入,jshell是java的控制台

安装完jdk并且配置好环境变了后,在系统的控制台输入jshell会进入Java的控制台,如下图
在这里插入图片描述

在jshell中可以直接输入java代码,例如:System.out.println("123")

在jshell中命令都是以/开头,例如
帮助命令/help
列出到当前位置输入的java代码/list
前面我执行了System.out.println("123")可以不用加分号也能使用
在这里插入图片描述

修改之前输入的java代码/edit
在这里插入图片描述
列出前面定义的所有变量/vars
在这里插入图片描述
列出已声明的方法/methods
在这里插入图片描述
删除前面输入的命令/drop 行号 或 id 或者 名称(变量名、方法名、对象名 等)
在这里插入图片描述
执行之前的代码/id 或者 /id的范围 或者 /多个id空格隔开
例如:/1 或者/9-14 或者/7 9
分别表示执行id=1的代码,id=9到14的代码,执行id=7 和 id=9的代码

注意:执行的代码会加入到缓存代码中,执行完后输入/list可以知道缓存中的代码。

在这里插入图片描述
执行上一次输入的命令/!

在这里插入图片描述
导包/imports默认情况下只导入了java.lang.*下所有类,如果需要是呀多线程等包可以直接通过该命令一次性导入。
在这里插入图片描述
导入文件/open代码
可以通过tab键提示和补全,例如下面我通过/open 打开D盘的文件在这里插入图片描述

执行之前的代码,并加入
查看历史执行命令/history
在这里插入图片描述
清空之前所有输入的命令/reset
在这里插入图片描述

退出jshell控制台/exit命令这个命令不用讲,就是退出jshell的。
还有/env/set/reloadsave等命令
下面是jshell的所有命令原生的说明
在这里插入图片描述

四、新特性:多版本兼容jar包

多版本兼容jar可以根据java环境使用特定的class
例如java8使用A类,由于java9的新特性,导致A类使用java9的新特性进行重写,那么当我环境换到了java9环境下,我需要使用拥有新特性的A类,那么可以这样做
META-INF目录下 MANIFEST.MF文件新增了一个属性:

Multi-Release: true

然后javac编译后,在jar命令打包过程中,通过--release参数指定java版本
如下方式创建jar包

jar --create --file demo.jar
    -C com.jdk8/build/classes .
    --release 9 -C com.jdk9/build/classes .

这样会自动识别不同版本的jdk使用哪一个路径下的类

五、新特性:interface中可以定义private方法

java8中可以有default声明的方法以及static方法,在java9中可以定义private的方法

六、新特性:钻石操作符升级< >

jdk8中可以使用<>省略泛型,因为可以通过上下文推断出泛型。
例如Set<String> set = new HashSet<>();
由于<>像钻石,因此倍称为砖石操作符,在java9中升级了该操作符,作用是用在匿名内部类上,也就是Set<String> set = new HashSet<>(){};,可以在原来的基础上通过{}符号创建简单的HashSet匿名子类,主要的作用是可以通过匿名子类重写父类的方法,因为父类的方法可能不满足需求,需要重写父类方法。

举例:在jdk9环境下

1、可以重写父类方法

Set<String> set=new HashSet<>(){
    
    
	//重写HashSet父类方法
    @Override
    public boolean isEmpty() {
    
    
    	//自己重写方法体,这里只是做一个例子
        return super.isEmpty();
    }
};

一个砖石语法的巧妙用法示例:

2、给添加数据,非静态代码块实现

	Set<String> set = new HashSet<>() {
    
    
	    {
    
    
	        add("张三");
	        add("李四");
	        add("王五");
	        add("赵六");
	    }
	};
	//便利集合
	set.stream().forEach(System.out::println);

七、新特效:try语句升级

在以前的try...cacth的写法是

try {
    
    
}catch (Exception e){
    
    
}

java9try可以有()

try (){
    
      
}catch (Exception e){
    
      
}

多了这个()有什么作用呢?
举例:
try()中的流不需要关闭,会自动关闭,并且对于使用多个流,在()中用;隔开即可。

InputStreamReader reader=new InputStreamReader(System.in);
OutputStreamWriter writer=new OutputStreamWriter(System.out);
try(reader;writer) {
    
    //隐式声明为final,所以在后面如果对reader重新赋值会报错
	//reader=null;这一行会报错,不允许重新赋值
    reader.read();
    writer.append("test");
}catch (IOException e){
    
    
    e.printStackTrace();
}

而在java8中代码应该这样写,需要手动关闭并且需要手动添加final

final InputStreamReader reader=new InputStreamReader(System.in);
final OutputStreamWriter writer=new OutputStreamWriter(System.out);
try {
    
    
    reader.read();
    writer.append("test");
}catch (IOException e){
    
    
    e.printStackTrace();
}finally {
    
    
    if (reader!=null){
    
    //手动关闭
        try {
    
    
            reader.close();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
    }
    if (writer!=null){
    
     //手动关闭
        try {
    
    
            writer.close();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
    }
}

八、新特性:限制下划线命名

在java的命名规范中变量名不能以数字开头,允许以字母或者_开头,但是java9中对_有限制,就是不能直接单独用_作为变量名(可能这个符合会作为关键字)
java9中依然可以用_开头作为变量名。就是不允许单独的_作为变量名。
在这里插入图片描述

九、新特性:String底层存储结构的改变

java9以前存储字符串底层用的是char[],在java9中采用byte[],之所以这样改变时因为多数情况下使用的是拉丁字符,而一个拉丁字符只需要使用一个byte存储,官方文档意思是说如果使用char型数组存储拉丁字符就会浪费一半的空间(一个char需要有2个byte)。

java8中:
java8中的String
java9中:
jdk9中的String

java9中怎么处理中文字符呢?

中文字符通过一个encoding-flag标识中文字符
在使用方面没有什么差别,就是在底层有了改变

十、新特性:快速创建只读集合

定义好的集合类肯定无法创建只读集合,所以得将已有的集合数据复制一份,并且设置进行调用添加数据的时候会报java.lang.UnsupportedOperationException异常

java8的示例代码:
Set<String> set = new HashSet<>() {
    
    
    {
    
    
        add("张三");
        add("李四");
        add("王五");
        add("赵六");
    }
};
//import java.util.Collections  是java.util包下的,java.util.stream也有一个同名的类,是流操作用的工具类
Set<String> unmodSet = Collections.unmodifiableSet(set);
unmodSet.add("123");//会报异常:UnsupportedOperationException

类似的还有ArrayList等集合类,都是以unmodifiableXXX()命名,需要传入一个集合实例返回的集合是只读集合

java9的示例代码:

直接调用interface中的static什么的of方法实现只读集合

Set<String> set = Set.of("张三", "李四", "王五", "赵六");
set.add("123");//只读同样会报错

List<String> list=List.of("张三", "李四", "王五", "赵六");
list.add("456");//只读同样会报错

//map的方式一:
Map<String,String>map=Map.of("key1","张三","key2","李四","key3","王五","key4","赵六");
//map的方式二:
Map<String, String> map2 = Map.ofEntries(Map.entry("key1", "张三"), Map.entry("key2", "李四"), Map.entry("key3", "王五"));
map.put("key5","789");//只读同样会报错
map2.put("key5","789");//只读同样会报错

十一、新特性:增强的StreamApi

Stream流操作新增方法一:default Stream<T> takeWhile(Predicate<? super T> predicate)

Stream中的源码:

default Stream<T> takeWhile(Predicate<? super T> predicate) {
    
    
    Objects.requireNonNull(predicate);
    // Reuses the unordered spliterator, which, when encounter is present,
    // is safe to use as long as it configured not to split
    return StreamSupport.stream(
            new WhileOps.UnorderedWhileSpliterator.OfRef.Taking<>(spliterator(), true, predicate),
            isParallel()).onClose(this::close);
}

示例代码:

List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 7, 8);
list.stream().takeWhile(x -> x < 5);//返回1,2,3,4的流,后面的不会再遍历,而filter会接着遍历,断言条件是否成立

List<Integer> list2 = List.of(1, 4, 3, 6, 2, 6, 9, 8);
list2.stream().takeWhile(x -> x < 6);//返回1,4,3的流

filter()方法不同的是,takeWhile不会遍历所有元素,而是当条件不成立时就会结束,相当于将断言的结果作为whlie循环遍历的条件,条件不成立,循环遍历结束

Stream流操作新增方法二:default Stream<T> dropWhile(Predicate<? super T> predicate)

Stream中的源码:

default Stream<T> dropWhile(Predicate<? super T> predicate) {
    
    
    Objects.requireNonNull(predicate);
    // Reuses the unordered spliterator, which, when encounter is present,
    // is safe to use as long as it configured not to split
    return StreamSupport.stream(
            new WhileOps.UnorderedWhileSpliterator.OfRef.Dropping<>(spliterator(), true, predicate),
            isParallel()).onClose(this::close);
}

takeWhile相反,是条件成立时,前面全部丢掉,留下条件成立后的后面所有元素
示例代码

List<Integer> list2 = List.of(1, 4, 3, 6, 2, 6, 9, 8);
list2.stream().dropWhile(x -> x < 6);//返回6,2,6,9,8
Stream流操作新增方法三:public static<T> Stream<T> ofNullable(T t)

Stream中源码

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

java8中不允许集合中只有一个元素,并且这个元素为null
例如:

Stream<Object> objectStream = Stream.of(null);//会报空指针异常 java.lang.NullPointerException
System.out.println(objectStream.count());//前面报错终止了

如果想创建一个null流在java9中可以通过ofNullable方法创建

Stream<Object> objectStream = Stream.ofNullable(null);
System.out.println(objectStream.count());//返回0
Stream流操作新增方法四:public static<T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next)

重载迭代方法,之前的是2个参数的,新增的这个方法是3个参数的
在java8中通过迭代可以创建无限流,会发现不能终止,除非超出范围报异常
所以该方法的出现是为了更好的控制流,让它有个终止条件
原先的2个参数的迭代方法一个是初始值,一个是迭代规则
新增的3个参数的迭代方法,一个是初始值,一个是终止条件,一个是迭代规则
后面两个都是断言型接口。

新增的方法源码
public static<T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next) {
    
    
    Objects.requireNonNull(next);
    Objects.requireNonNull(hasNext);
    Spliterator<T> spliterator = new Spliterators.AbstractSpliterator<>(Long.MAX_VALUE,
           Spliterator.ORDERED | Spliterator.IMMUTABLE) {
    
    
        T prev;
        boolean started, finished;

        @Override
        public boolean tryAdvance(Consumer<? super T> action) {
    
    
            Objects.requireNonNull(action);
            if (finished)
                return false;
            T t;
            if (started)
                t = next.apply(prev);
            else {
    
    
                t = seed;
                started = true;
            }
            if (!hasNext.test(t)) {
    
    
                prev = null;
                finished = true;
                return false;
            }
            action.accept(prev = t);
            return true;
        }

        @Override
        public void forEachRemaining(Consumer<? super T> action) {
    
    
            Objects.requireNonNull(action);
            if (finished)
                return;
            finished = true;
            T t = started ? next.apply(prev) : seed;
            prev = null;
            while (hasNext.test(t)) {
    
    
                action.accept(t);
                t = next.apply(t);
            }
        }
    };
    return StreamSupport.stream(spliterator, false);
}
2个参数的iterator()源码
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {
    
    
    Objects.requireNonNull(f);
    Spliterator<T> spliterator = new Spliterators.AbstractSpliterator<>(Long.MAX_VALUE,
           Spliterator.ORDERED | Spliterator.IMMUTABLE) {
    
    
        T prev;
        boolean started;

        @Override
        public boolean tryAdvance(Consumer<? super T> action) {
    
    
            Objects.requireNonNull(action);
            T t;
            if (started)
                t = f.apply(prev);
            else {
    
    
                t = seed;
                started = true;
            }
            action.accept(prev = t);
            return true;
        }
    };
    return StreamSupport.stream(spliterator, false);
}
Optional新增方法:public Stream<T> stream()

Optional提供了转换Stream的方法,相当于在原来4种方法,变成了5种
源码

public Stream<T> stream() {
    
    
    if (!isPresent()) {
    
    
        return Stream.empty();
    } else {
    
    
        return Stream.of(value);
    }
}

示例代码:

Optional<ArrayList<String>> optionalStream = Optional.ofNullable(new ArrayList<String>() {
    
    
    {
    
    
        add("123");
        add("456");
        add("789");
    }
});
Stream<String> list = optionalStream.stream().flatMap(x -> x.stream());
list.forEach(System.out::println);

下面的新特性,作为了解内容,后期新特性如果遇到了再总结出来


十二、新特性:多分辨率图像

作用就是在不同分辨率的屏幕下能够自动转换图片比例大小。这个掠过

十三、新特性:新的Http客户端Api—在jdk14中有改动

这个模块在后期的java14版本模块变了,变成了java.net.http模块

官网文档jdk14得HttpClient使用案例文档
我得使用案例
首先需要引入模块,在module-info.java中添加

module demo {
    
    
    requires java.net.http;//HttpClient类得
}
HttpRequest httpRequest = HttpRequest.newBuilder(URI.create("http://www.baidu.com")).GET().build();
HttpClient client = HttpClient.newBuilder()
        .version(HttpClient.Version.HTTP_2)//支持 Http2.0, http1.1直接Version.HTTP_1_1
        .followRedirects(HttpClient.Redirect.NORMAL)
        .connectTimeout(Duration.ofSeconds(20))
//                .proxy(ProxySelector.of(new InetSocketAddress("proxy.example.com", 80)))
//                .authenticator(Authenticator.getDefault())
        .build();
HttpResponse<String> response = client.send(httpRequest, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());

打印结果:
在这里插入图片描述

十四、新特性:Deprecated的Api

Java 9 废弃或者移除了几个不常用的功能。其中最主要的是 Applet API,现在是标记为废弃的。
随着对安全要求的提高,主流浏 览器已经取消对 Java 浏览器插件的支持。

HTML5 的出现也进一步加 速了它的消亡。开发者现在可以使用像 Java Web Start 这样的技术来 代替 Applet,它可以实现从浏览器启动应用程序或者安装应用程序。
同时,appletviewer 工具也被标记为废弃。

十五、新特性:智能java编译工具

关于智能java编译器sjavac命令,官方文档地址:http://openjdk.java.net/jeps/199
再后期版本中废弃了
在这里插入图片描述

十六、新特性:统一的JVM日志系统

日志是解决问题的唯一有效途径:
曾经很难知道导致 JVM 性能 问题和导致 JVM 崩溃的根本原因。
不同的 JVM 日志的碎片化和日志 选项(例如:JVM 组件对于日志使用的是不同的机制和规则) ,这使 得 JVM 难以进行调试。

解决该问题最佳方法:

对所有的JVM组件引入一个单一的系统, 这些 JVM 组件支持细粒度的和易配置的 JVM 日志

十七、新特性:javadoc的Html5支持

jdk 8 :生成的 java 帮助文档是在 HTML 4 中。
jdk 9 :javadoc 的输出,现在符合兼容 HTML 5 标准。

java 9 中生成的文档,添加了一个搜索框,可以直接通过文档搜索
在这里插入图片描述

十八、新特性:改进javaScript的Nashorn引擎

Nashorn 项目在 JDK 9 中得到改进,它为 Java 提供轻量级的 Javascript 运行时。Nashorn 项目跟随 Netscape 的 Rhino 项目,目 的是为了在 Java 中实现一个高性能但轻量级的 Javascript 运行时。
Nashorn 项目使得 Java 应用能够嵌入 Javascript。
它在 JDK 8 中为 Java 提供一个 Javascript 引擎。
JDK 9 包含一个用来解析 Nashorn 的 ECMAScript 语法树的 API。
该 API 使得 IDE 和服务端框架不需要依赖 Nashorn 项目的 内部实现类,就能够分析ECMAScript 代码

注意:再后期版本Nashorn引擎中被弃用了,在java11弃用了

十九、新特性:java的动态编译器

java编写的java文件需要通过java编译器编译成class文件,和C/C++相比,java的编译文件不是可以直接运行的机器码,因此没有C/C++更省内存,且效率高,因此有了java的JIT编译器

JIT(Just-in-time)编译器可以在运行时将热点编译成本地代码, 速度很快。现9中还不够完善,后期版本可能会改进值得期待

猜你喜欢

转载自blog.csdn.net/qq_41813208/article/details/107526595