Java10&Java11新特性——代码示例
作者:互联网
Java10
2018年3月发布,Java9和Java10都不是长期支持的版本。JAVA11是长期支持的版本。
JDK10一共定义了109个新特性,其中包含12个JEP(对于程序员来讲,真 正的新特性其实就一个),还有一些新
API和JVM规范以及JAVA语言规范上 的改动。
JEP是指(JDK Enhancement Proposal特性加强提议)
局部变量类型推断
产生背景
开发者经常抱怨Java中引用代码的难度,局部变量的显示类型声明,常常被认为是不必须的。
好处
减少了啰嗦和形式的代码,避免了信息冗余,而且对齐了变量名,方便阅读
举例如下
场景一:类实例化时
在声明一个变量时,总是习惯了敲打两次变量类型,第一次用于声明变量类型,第二次用于构造器。
LinkedHashSet<Integer> set = new LinkedHashSet<>();
场景二:返回值类型含复杂泛型结构。
变量的声明类型书写复杂且较长,尤其加上泛型的使用
Iterator<Map.Enter<Integer,Student>> iterator = set.iterator();
场景三
URL url = new URL("www.baidu.com");
URLConnection urlConnection = url.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
jdk10之后,可使用var代替,有些类似于js
public void test02() {
//int num = 10;
//java10之后,声明变量时,根据所附的值推断类型的变量。
var num = 10;
var list = new ArrayList<String>();
list.add("123");
//遍历操作
for (var n : list) {
System.out.println(n);
}
}
不适用情况
有一些四种场景,六种结构不能使用
四种场景:
- 变量不赋值不能进行类型推断
- lambda表达式只能赋给函数式接口,使用var的话,会不知道左边是否为接口
- 方法引用中,原因和上述类似
- 数组静态初始化中
public void test() {
//1、不赋值不能进行类型推断
// var num;
Supplier<Double> sup = () -> Math.random();
//2、lambda表达式只能赋给函数式接口,使用var的话,会不知道左边是否为接口
// var sup2 = Math::random;
//3、方法引用中,原因和上述类似
Consumer<String> con = System.out::println;
//var con1 = System.out::println;
//4、数组静态初始化中
int[] arr = new int[]{1, 2, 3, 4};
//正常
var arr2 = new int[]{1, 2, 3, 4};
int[] arr4 = {1, 2, 3, 4};
//错误,无法推断类型
// var arr3 = {1,2,3,4};
}
六种结构
- 情况1:没有初始化的局部变量声明
- 情况2:方法的返回类型
- 情况3:方法的参数类型
- 情况4:构造器的参数类型
- 情况5:属性
- 情况6:catch块
public class TyteInference {
@Test
public void test03() {
//情况1:没有初始化的局部变量声明
var num = null;
//情况2:方法的返回类型
method();
//情况3:方法的参数类型
//情况4:构造器的参数类型
//情况5:属性
//情况6:catch块
try{}catch (var e){}
}
//情况2,因为方法是根据返回值决定里面的
public var method(){
return 1;
}
//情况3:方法的参数类型。同样改变了方法的初衷,根据形参类型来要求参数,
//如果写成这样,就相当于传什么类型都可以
public void method(var num){}
//情况4:构造器的参数类型,原因同上
public TyteInference(var i){}
//情况5:属性,因为属性在JVM中初始化时会有默认值,如果用var就无法判断
var num = 10;
}
原理
在处理var时,编译器先是查看表达式右边部分,并根据右边变量值的类型进行 推断,作为左边变量的类型,然后
将该类型写入字节码当中(也就是说,在字节码文件中,var会被重新编译成右边对应的类型)
注意点
-
var不是一个关键字
你不需要担心变量名或方法名会与 var发生冲突,因为 var实际上并不是一个关键字, 而是一个类型名,只有在编译器需要知道类型的地方才需要用到它。除此之外,它 就是一个普通合法的标识符。也就是说,除了不能用它作为类名,其他的都可以, 但极少人会用它作为类名。
-
这不是JavaScript
var并不会改变Java是一门静态类型语言的事实。编译器负责推 断出类型,并把结果写入字节码文件,就好像是开发人员自己敲入类型一样。
集合新增创建不可见集合的方法
自java9开始,jdk为集合都增加了of方法(java9新增)和copyof方法(java10新增)
public void test01() {
//示例1:
var list1 = List.of("Java", "Python", "C");
var copy1 = List.copyOf(list1);
System.out.println(list1 == copy1); // true
//示例2:2710427426
var list2 = new ArrayList<String>();
//list2不是只读的,所以copyOf会新建一个只读集合,
//如果参数本身就是只读集合,则返回值为当前的coll
var copy2 = List.copyOf(list2);
System.out.println(list2 == copy2); // false
//示例1和2代码基本一致,为什么一个为true,一个为false?
}
Java11
- 新增了一些字符串的处理方法
- Optional加强
- 局部变量类型推断升级
- 全新的HTTP客户端API
- 更简化的编译运行程序
- 废除Nashorn引擎
从JVM角度,JDK11引入了两种新的GC,其中包括划时代意义的ZGC
新增了一些字符串的处理方法
public void test01() {
//判断是否为空串(去掉空格、制表符等)
System.out.println("".isBlank());
//去除首尾空白(包括制表符)
System.out.println(" \nssd ".strip());
//去除尾部空白
System.out.println(" ss ".stripTrailing());
//去除头部空白
System.out.println(" ss ".stripLeading());
//将字符串重复n次,结果为aaaaaaaaaa
System.out.println("aa".repeat(5));
//统计行数,结果为3
System.out.println("A\n\nds\n".lines().count());
}
Optional加强
现在可以将一个Opitonal转换为一个Stream,或者当一个空Optional时给它一个替代的
局部变量类型推断升级
允许在使用lambda表达式时,给参数加注解
//错误形式,必须要有类型
//Consumer com = (@Deprecated t)->{System.out.println(t);};
//java11之后,
//使用lambda表达式时可以给参数上加注解
Consumer<String> com1 = (@Deprecated var t)->{System.out.println(t);};
全新的HTTP客户端API
Java9中已经引进,在Java11中正式可用
它将替换HttpURLConnection,并提供对WebSocket和HTTP/2的支持
更简化的编译运行程序
在jdk11之前,命令行运行java文件,必须先编译后运行
javac HelloWorld.java
java HelloWorld
在jdk11之后
java HelloWorld.java
需要注意的点:
- 执行源文件中的第一个类, 第一个类必须包含主方法
- 并且不可以使用其它源文件中的自定义类, 本文件中的自定义类是可以使用的
废除Nashorn引擎
有需要的可以考虑使用GraalVM
标签:Java11,Java10,示例,System,类型,var,println,public,out 来源: https://blog.csdn.net/qq_40500437/article/details/111409740