- Java9新特性
- jdk目录结构的改变
- java9新特性:模块化系统
- java9新特性:Java的REPL工具:jshell
- java9新特性:接口中声明私有方法
- java9新特性:钻石操作符的语法升级
- java9新特性:try结构的语法升级
- java9新特性:String底层存储结构的变更
- java9新特性:集合工厂方法创建只读集合
- java9新特性:InputStream中的transferTo()方法
- java9新特性:StreamAPI新增的4个方法
- java9新特性:Optional的新方法stream()
- Java 10 的新特性
- java10新特性:局部变量类型推断
- java10新特性:集合新增创建不可变集合的方法
- Java 11 的新特性
- java11新特性:String新增的方法
- java11新特性:Optional新增的方法
- java11新特性:局部变量类型推断的升级
- java11新特性:HttpClient
- java11新特性:简化编译运行程序 Java命令
- Java语言高级-java11新特性:其它新特性
- ZGC (垃圾回收器)
- 其他的新特性
- 在当前JDK中看不到什么?新的货币API
- 关于JDK版本
- 新版本jdk的下载与IDEA开发环境的设置
-
用模块来管理各个package,通过声明某个package暴露,模块(module)的概念,其实就是package外再裹一层,不声明默认就是隐藏。因此,模块化使得代码组织上更安全,因为它可以指定哪些部分可以暴露,哪些部分隐藏。
-
实现目标
模块化的主要目的在于减少内存的开销
- 只需必要模块,而非全部jdk模块,可简化各种类库和大型应用的开发和维护
- 改进Java SE 平台,使其可以适应不同大小的计算设备
- 改进其安全性,可维护性,提高性能
-
模块将由通常的类和新的模块声明文件(module-info.java)组成。该文件是位于java代码结构的顶层,该模块描述符明确地定义了我们的模块需要什么依赖关系,以及哪些模块被外部使用。在exports子句中未提及的所有包默认情况下将封装在模块中,不能在外部使用。
-
案例结构
-
Person类
package git;
@Data
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
- module-info.java——JDK9Test中
module JDK9Test {
exports git; //exports 包名--》将包暴露使用
}
- module-info.java——day13中
module day13 {
requires JDK9Test; //requires 包名---》接收包
requires junit;//若要调用JDK9以上版本的测试类,需要引入
exports github;
}
- ModuleTest类
import git.Person;
public class ModuleTest {
public static void main(String[] args) {
Person p = new Person("Jack",20);
System.out.println(p);
}
}
// Person{name='Jack', age=20}
java9新特性:Java的REPL工具:jshell
-
产生背景
像Python和Scala之类的语言早就有交互式编程环境REPL(read-evaluate-print-loop)了,以交互式的方式对语句和表达式进行求值。开发者只需要输入一些代码,就可以在编译前获得对程序的反馈。而之前的Java版本要想执行代码,必须创建文件、声明类、提供测试方法方可实现。
-
设计理念
- 即写即得、快速运行
-
实现目标
- Java 9 中终于拥有了REPL工具:jShell。让Java可以像脚本语言一样运行,从控制台启动jShell,利用jShell在没有创建类的情况下直接声明变量,计算表达式,执行语句。即开发时可以在命令行里直接运行Java的代码,而无需创建Java文件,无需跟人解释”public static void main(String[] args)”这句废话。
- jShell也可以从文件中加载语句或者将语句保存到文件中。
- jShell也可以是tab键进行自动补全和自动添加分号。
jShell 具体使用, 自行了解
java9新特性:接口中声明私有方法- Java8中规定接口中的方法除了抽象方法之外,还可以定义静态方法和默认的方法。一定程度上,扩展了接口的功能,此时的接口更像是一个抽象类。
- 在Java9中,接口更加的灵活和强大,连方法的访问权限修饰符都可以声明为private的了,
此时方法将不会成为你对外暴露的API的一部分
public interface MyInterface {
//如下的三个方法的权限修饰符都是public
void methodAbstract();
static void methodStatic(){
System.out.println("这是接口中的静态方法");
}
default void methodDefault(){
System.out.println("这是接口中的默认方法");
methodPrivate();
}
//jdk 9中允许接口中定义私有的方法
private void methodPrivate(){
System.out.println("这是接口中的私有方法");
}
}
public class MyInterfaceImpl implements MyInterface{
@Override
public void methodAbstract() {
}
@Override
public void methodDefault() {
System.out.println("实现类重写了接口中的默认方法");
}
public static void main(String[] args) {
//接口中的静态方法只能由接口自己调用
MyInterface.methodStatic();
// 接口的实现类不能调用接口的静态方法
// MyInterfaceImpl.methodStatic();
MyInterfaceImpl impl = new MyInterfaceImpl();
impl.methodDefault();
// 接口的私有方法,不能在接口外部调用
// impl.methodPrivate();
}
}
java9新特性:钻石操作符的语法升级
- 我们将能够与匿名实现类共同使用钻石操作符(diamondoperator)在Java8中如下的操作是会报错的
//java9特性5:钻石操作符的升级
@Test
public void test2(){
//钻石操作符与匿名内部类在java 8中不能共存。在java9可以。
Comparator com = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return 0;
}
};
//jdk7中的新特性:类型推断
ArrayList list = new ArrayList();
}
- 编译报错信息:Cannotuse“”with anonymous inner classes.
import org.junit.Test;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Comparator;
public class Java9Test {
// try操作的升级
public static void main(String[] args) {
//java 8之前的资源关闭的操作
// InputStreamReader reader = null;
// try {
// reader = new InputStreamReader(System.in);
// char[] cbuf = new char[20];
// int len;
// if((len = reader.read(cbuf) )!= -1){
// String str = new String(cbuf,0,len);
// System.out.println(str);
// }
// } catch (IOException e) {
// e.printStackTrace();
// } finally {
// if(reader != null){
// try {
// reader.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
// }
//java 8中资源关闭操作: Java 8 中,可以实现资源的自动关闭
//要求自动关闭的资源的实例化必须放在try的一对小括号中
// try(InputStreamReader reader = new InputStreamReader(System.in)){
// char[] cbuf = new char[20];
// int len;
// if((len = reader.read(cbuf) )!= -1){
// String str = new String(cbuf,0,len);
// System.out.println(str);
// }
// } catch (IOException e) {
// e.printStackTrace();
// }
//java9中资源关闭操作:需要自动关闭的资源的实例化可以放在try的一对小括号外。
//此时的资源属性是常量,声明为final的,不可修改
InputStreamReader reader = new InputStreamReader(System.in);
try (reader) {
char[] cbuf = new char[20];
int len;
if((len = reader.read(cbuf) )!= -1){
String str = new String(cbuf,0,len);
System.out.println(str);
}
// reader = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
java9新特性:String底层存储结构的变更
-
String再也不用char[]来存储啦,改成了byte[]加上编码标记,节约了一些空间。
public final class String implements java.io.Serializable, Comparable, CharSequence { @Stableprivate final byte[] value; }
-
那StringBuffer和StringBuilder呢?
也改为byte[]数组
- 创建一个只读、不可改变的集合,必须构造和分配它,然后添加元素,最后包装成一个不可修改的集合。
- 构造,分配,添加元素之后, 就不能对该不可变集合进行CRUD操作,否则抛出异常
java.lang.UnsupportedOperationException
- 构造,分配,添加元素之后, 就不能对该不可变集合进行CRUD操作,否则抛出异常
import org.junit.Test;
import java.util.*;
public class Java9Test2 {
//java9新特性八:集合工厂方法:创建只读集合
//java8中的写法:
@Test
public void test() {
List namesList = new ArrayList();
namesList.add("Joe");
namesList.add("Bob");
namesList.add("Bill");
//返回的namesList是一个只读的集合
namesList = Collections.unmodifiableList(namesList);
namesList.add("Franck"); // 抛出异常
System.out.println(namesList);
}
@Test
public void test2(){
List list = Collections.unmodifiableList(Arrays.asList("a", "b", "c"));
Set set = Collections.unmodifiableSet(new HashSet(Arrays.asList("a", "b", "c")));
// 如下操作不适用于jdk 8 及之前版本,适用于jdk 9
Map map = Collections.unmodifiableMap(new HashMap() {
{
put("a", 1);
put("b", 2);
put("c", 3);
}
});
map.forEach((k, v) -> System.out.println(k + ":" + v));
}
@Test
public void test3() {
//此时得到的集合list也是一个只读集合。
List list = Arrays.asList(1, 7, 9, 3, 2);
//报异常
list.add(6);
}
@Test
public void test4() {
List list1 = List.of(1, 2, 3, 4, 5);
//不能添加
// list1.add(6);
System.out.println(list1);
Set set1 = Set.of(23, 3, 54, 65, 43, 76, 87, 34, 46);
//不能添加
// set1.add(4);
System.out.println(set1);
Map map1 = Map.of("Josh", 23, "Jack", 54, "Franck", 12);
//不能添加
//map1.put("George",34);
System.out.println(map1);
Map map2 = Map.ofEntries(Map.entry("Josh", 34), Map.entry("Jim", 21));
// map2.put("George",34);
System.out.println(map2);
}
}
java9新特性:InputStream中的transferTo()方法
InputStream 终于有了一个非常有用的方法:transferTo,可以用来将数据直接传输到OutputStream,这是在处理原始数据流时非常常见的一种用法,如下示例。
import org.junit.Test;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class Java9Test2 {
//java9新特性九:InputStream的新方法:tranferTo()
@Test
public void test5() {
ClassLoader cl = this.getClass().getClassLoader();
try (InputStream is = cl.getResourceAsStream("hello.txt");
OutputStream os = new FileOutputStream("src\\hello1.txt")) {
is.transferTo(os); // 把输入流中的所有数据直接自动地复制到输出流中
} catch (IOException e) {
e.printStackTrace();
}
}
}
java9新特性:StreamAPI新增的4个方法
- 在Java 9 中,Stream API 变得更好,Stream 接口中添加了4 个新的方法:takeWhile, dropWhile, ofNullable,还有个 iterate 方法的新重载方法,可以让你提供一个Predicate (判断条件)来指定什么时候结束迭代。
- 除了对Stream 本身的扩展,Optional 和Stream 之间的结合也得到了改进。现在可以通过Optional 的新方法stream() 将一个Optional 对象转换为一个(可能是空的) Stream 对象。
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class Java9Test3 {
//java9新特性十:Stream API的加强
@Test
public void test(){
List list = Arrays.asList(23, 43, 45, 55, 61, 54, 32, 2, 45, 89, 7);
//takeWhile 返回从开头开始的按照指定规则尽量多的元素
// list.stream().takeWhile(x -> x < 60).forEach(System.out::println);
// 移除指定条件的元素
//dropWhile():与 takeWhile 相反,返回剩余的元素。
list.stream().dropWhile(x -> x x + 1).limit(10).forEach(System.out::println);
//java9中新增的重载的方法
// 从0开始, 每次递增1, 但递增的结果要 x x + 1).forEach(System.out::println);
}
}
java9新特性:Optional的新方法stream()
//java9新特性十一:Optional提供了新的方法stream()
@Test
public void test4(){
List list = new ArrayList();
list.add("Tom");
list.add("Jerry");
list.add("Tim");
Optional optional = Optional.ofNullable(list);
Stream stream = optional.stream();
// long count = stream.count();
// System.out.println(count);
stream.flatMap(x -> x.stream()).forEach(System.out::println);
}
Java 10 的新特性
java10新特性:局部变量类型推断
-
产生背景
开发者经常抱怨Java中引用代码的程度。局部变量的显示类型声明,常常被认为是不必须的,给一个好听的名字经常可以很清楚的表达出下面应该怎样继续。
-
好处:减少了啰嗦和形式的代码,避免了信息冗余,而且对齐了变量名,更容易阅读!
-
举例如下:
-
场景一:类实例化时
作为Java开发者,在声明一个变量时,我们总是习惯了敲打两次变量类型,第一次用于声明变量类型,第二次用于构造器。
LinkedHashSet set= new LinkedHashSet();
-
场景二:返回值类型含复杂泛型结构
变量的声明类型书写复杂且较长,尤其是加上泛型的使用
Iterator iterator= set.iterator();
-
场景三:我们也经常声明一种变量,它只会被使用一次,而且是用在下一行代码中,比如:
URL url= new URL("https://www.waysto.work/"); URLConnection connection= url.openConnection(); Reader reader= newBufferedReader(new InputStreamReader(connection.getInputStream()));
-
import org.junit.Test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
public class JDK10Test {
/**
* java10新特性一:局部变量的类型推断
*/
@Test
public void test(){
//1.声明变量时,根据所附的值,推断变量的类型
var num = 10;
var list = new ArrayList();
list.add(123);
//2.遍历操作
for (var i : list) {
System.out.println(i);
System.out.println(i.getClass());
}
//3.普通的遍历操作
for (var i = 0; i Math.random();
// var sup = () -> Math.random();
//3.方法引用中,左边的函数式接口不能声明为var
// Consumer con = System.out::println;
// var con = System.out::println;
//4.数组的静态初始化中,注意如下的情况也不可以
int[] arr = {9, 5, 2, 7};
// var arr = {9,5,2,7};
}
@Test
public void test3() {
// 情况1:没有初始化的局部变量声明
// var s = null;
// 情况6:catch块
// try{
//
// }catch(var e){
// e.printStackTrace();
// }
}
//情况2:方法的返回类型
// public var method1(){
//
return 0;
// }
// 情况3:方法的参数类型
// public void method2(var num){
//
// }
//情况4:构造器的参数类型
// public Java10Test(var i){
//
// }
//情况5:属性
// var num;
@Test
public void test4() {
try {
var url = new URL("http://www.waysto.work/");
var connection = url.openConnection();
var reader = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
}
-
工作原理
在处理var时,编译器先是查看表达式右边部分,并根据右边变量值的类型进行推断,作为左边变量的类型,然后将该类型写入字节码当中。
-
注意
-
var不是一个关键字
-
你不需要担心变量名或方法名会与var发生冲突,因为var实际上并不是一个关键字,而是一个类型名,只有在编译器需要知道类型的地方才需要用到它。除此之外,它就是一个普通合法的标识符。也就是说,除了不能用它作为类名,其他的都可以,但极少人会用它作为类名。
-
这不是JavaScript
-
首先我要说明的是,var并不会改变Java是一门静态类型语言的事实。编译器负责推断出类型,并把结果写入字节码文件,就好像是开发人员自己敲入类型一样。下面是使用IntelliJ(实际上是Fernflower的反编译器)反编译器反编译出的代码
- 自Java9开始,Jdk里面为集合(List/Set/Map)都添加了of (jdk9新增)和copyOf(jdk10新增)方法,它们两个都用来创建不可变的集合,来看下它们的使用和区别。
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class JDK10Test {
//java10的新特性二:集合中新增的copyOf(),用于创建一个只读的集合
@Test
public void test5(){
//示例1:
// list1 本身就是不可变集合
var list1 = List.of("Java", "Python", "C");
// copyof后, copy1也是不可变集合
var copy1 = List.copyOf(list1);
System.out.println(list1 == copy1); // true
//示例2:
// list2是可变集合
var list2 = new ArrayList();
list2.add("KKK");
// copyof后, copy2变为不可变集合
var copy2 = List.copyOf(list2);
System.out.println(list2 == copy2); // false
//示例1和2代码基本一致,为什么一个为true,一个为false?
//结论:copyOf(Xxx coll):如果参数coll本身就是一个只读集合,则copyOf()返回值即为当前的coll
//如果参数coll不是一个只读集合,则copyOf()返回一个新的集合,这个集合是只读的。
}
}
- 从 源 码 分 析,可以看出copyOf方 法 会 先 判 断 来 源 集 合 是 不 是AbstractImmutableList类型的,如果是,就直接返回,如果不是,则调用of创建一个新的集合。
- 示例2因为用的new创建的集合,不属于不可变AbstractImmutableList类的子类,所以copyOf方法又创建了一个新的实例,所以为false。
- 注意:使用of和copyOf创建的集合为不可变集合,不能进行添加、删除、替换、排序等操作,不然会报java.lang.UnsupportedOperationException异常。
- 上面演示了List的of和copyOf方法,Set和Map接口都有。
import org.junit.Test;
public class JDK11Test {
//java 11新特性一:String中新增的方法
@Test
public void test(){
// isBlank():判断字符串是否为空白
System.out.println(" \t \t \n ".isBlank());
// strip():去除首尾空白
System.out.println("++++" + " \t abc \t \n ".strip() + "++++");
System.out.println("++++" + " \t abc \t \n ".trim() + "++++");
// stripTrailing():去除尾部空格
System.out.println("++++" + " \t abc \t \n ".stripTrailing() + "++++");
// stripLeading():去除首部空格
System.out.println("++++" + " \t abc \t \n ".stripLeading() + "++++");
// repeat(int count):复制字符串
String str1 = "abc";
String str2 = str1.repeat(5);
System.out.println(str2);
// lines().count():行数统计
String str3 = "abc\nEFG\nH";
System.out.println(str3.lines().count());
}
}
java11新特性:Optional新增的方法
Optional也增加了几个非常酷的方法,现在可以很方便的将一个Optional转换成一个Stream,或者当一个空Optional时给它一个替代的。
新增方法描述新增的版本boolean isEmpty()判断value是否为空JDK 11ifPresentOrElse(Consumer最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?