@[TOC]
语法层次改变
钻石操作符号语法升级
钻石操作符,就是我们泛型使用的符号<>
JAVA8 中,匿名内部类不能使用钻石操作符,如下代码在JAVA8 中是报错的,匿名内部类这里不支持泛型推断,重写的方法不明确泛型
这里匿名内部类中的<>号里必须要和前面的声明保持一致,不能空着不写,这样重写的方法就根据匿名内部类的泛型
但是这种写法在JAVA9 中就允许了
而且在JAVA9中,匿名内部类的语法不仅仅可以用于接口和抽象类,普通类也可以通过匿名内部类写法,在某个实例上完成对某个方法的重写
public class Demo1 {
public static void main(String[] args) {
/*
* 匿名内部类仅仅在接口和抽象类上使用,作为一种快速的实现方式
* JAVA9中,普通类也可以借助这种语法形式实现对方法的快速临时的重写
* */
Person<String> person=new Person<>(){
@Override
public void eat(String s) {
super.eat(s);
}
};
person.eat("油条");
}
}
class Person<T>{
public void eat(T t){
System.out.println("Person eat");
}
}
try结构语法升级
普通的try catch finally语句 ,要释放的资源可以放到finally语句块中
public class Demo02 {
public static void main(String[] args) {
InputStreamReader reader =null;
try{
reader =new InputStreamReader(System.in);
int read = reader.read();
}catch (Exception e){
throw new RuntimeException(e);
}finally {
// 这里可以释放资源
if(null != reader){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
JAVA 8中已经对try语法进行了升级,可以将要释放的资源放到try后面的小括号中,这样就不用通过finally语句块释放资源了,但是要求执行后必须关闭的资源一定要放在try子句中进行初始化,否则编译不通过. 下面的案例中,reader必须放在try后面的小括号中进行初始化
public static void main(String[] args) {
try( InputStreamReader reader=new InputStreamReader(System.in) ){
int read = reader.read();
}catch (Exception e){
throw new RuntimeException(e);
}
}
JAVA 9 资源的关闭操作,可以在try子句中使用已经初始化的资源但是此时的资源必须是final修饰的,final可以省略不写
// JAVA9 try语法升级
public void testb() throws FileNotFoundException {
// JAVA9 try catch finally语句块
InputStreamReader isr =new InputStreamReader(new FileInputStream("d:/UserMapper.xml"));
OutputStreamWriter isw =new OutputStreamWriter(new FileOutputStream("d:/UserMapper1.xml"));
try( isr; isw){
isr.read();
}catch (Exception e){
e.printStackTrace();
}
}
下划线命名标识符的使用限制
标识符命名组成:字母,数字,下划线,$
JAVA8 中,可以使用一个 _ 作为标识符的命名
JAVA9 中,就不可以使用一个 _
作为标识符的命名了,但是标识符中仍然可以使用_
,必须配合其他内容
API层次的改变
接口中的私有方法
接口中的设计使用在JDK7、8、9中都有相关的变化的。
JAVA7 中,接口只能有抽象方法
JAVA8 中,接口中static(静态不可重写)和default(可以重写)修饰的方法可以拥有方法体
JAVA9 中,接口中可以使用private修饰方法,并拥有方法体,但是接口中的成员变量仍然不能用private修饰
代码案例
public class Demo4 {
// 接口,是一种规范和要求
// 实现多继承
}
// java7 接口中的方法必须都是抽象的
interface Inter1 {
void methoda();
}
// java8接口可以定义static/default修饰的非抽象方法
interface Inter2 {
void methoda();
static void methodB() {
}
default void methodC() {
}
}
// java9 允许定义私有的非抽象方法
interface Inter3 {
void methoda();
static void methodB() {
}
default void methodC() {
methodD();
}
private void methodD() {
}
}
String底层存储结构变化
JAVA8 中String类内部维护的是一个final修饰的私有char数组,说明String的底层是通过char数组存储字符串的。
JAVA9 中String的源码,String类内部维护的是一个final修饰的私有byte数组,说明String的底层是通过byte数组存储字符串的.
这么调整的原因:
在Java 9之前,如果要在代码中表示二进制数据,需要手动将二进制数据转换为字节数组,然后使用字节数组来创建String对象。这个过程比较繁琐,并且容易出错。
为了简化这个过程,Java 9引入了二进制字符串字面值。现在,可以直接在代码中使用前缀0b来表示二进制数据,并将其转换为String对象。例如:
String binaryString = "0b101010";
Stream新增4个API
JAVA9 中,Stream接口添加了4个新方法,takeWhile、dropWhile、ofNullable以及 iterate。
takeWhile是从流中的头开始取元素,直到不满足条件为止。
public static void testTakeWhile(){
List<Integer> list = Arrays.asList(1, 89, 63, 45, 72, 65, 41, 65, 82, 35, 95, 100);
// 从头开始取所有奇数,直到遇见一个偶数为止
list.stream().takeWhile(e-> e%2==1).forEach(System.out::println);
}
dropWhile 从头开始删除满足条件的数据,直到遇见第一个不满足的位置,并保留剩余元素
public static void testDropWhile(){
List<Integer> list = Arrays.asList(2, 86, 63, 45, 72, 65, 41, 65, 82, 35, 95, 100);
// 删除流开头所有的偶数,直到遇见奇数为止
list.stream().dropWhile(e-> e%2==0 ).forEach(System.out::println);
}
ofNullable 允许创建Stream流时只放入一个null
public static void testOfNullable(){
// of方法获取流 ,允许元素中有多个null值
Stream<Integer> stream1 = Stream.of(10, 20, 30, null);
// 如果元素中只有一个null,是不允许的
Stream<Integer> stream2 = Stream.of(null);
// JAVA9中,如果元素为null,返回的是一个空Stream,如果不为null,返回一个只有一个元素的Stream
Stream<Integer> stream3 = Stream.ofNullable(null);
}
iterate指定种子数、指定条件和迭代方式来获取流
public static void testNewIterate(){
//JAVA8通过 generate方法获取一个Stream
Stream.generate(Math::random).limit(10).forEach(System.out::println);
//JAVA8 通过iterate获取一个Stream
Stream.iterate(0,t-> t+2).limit(10).forEach(System.out::println);
//JAVA9通过重载iterate获取Stream
Stream.iterate(0,t -> t<10,t-> t+1).forEach(System.out::println);
}
除了Stream本身的扩展,Optional和Stream之间的结合也得到了改进,现在可以通过Optional的新方法将一个Optional对象转换为一个Stream对象(可能是空的)
/**
* Optional类新增Stream方法,可以将一个Optional转换为Stream
*/
public static void testOptionalStream(){
List<Integer> list =new ArrayList<>();
Collections.addAll(list,10,5,45,95,36,85,47);
Optional<List<Integer>> optional=Optional.ofNullable(list);
// 通过optional的Stream方法获取一个Stream
Stream<List<Integer>> stream = optional.stream();
// 以为内部的每个元素也是一个List,通过flatMap方法,将内部的List转换为Stream后再放入一个大Stream
stream.flatMap(x->x.stream()).forEach(System.out::println);
}
InputStream新增transferTo方法
InputStream新增transferTo方法,可以用来将数据直接传输到OutpuStream,这是在处理原始数据时非常常见的一种方法
InputStream inputStream =new FileInputStream("d:/aaa.txt");
OutputStream outputStream=new FileOutputStream("d:/bbb.txt");
try (inputStream;outputStream){
inputStream.transferTo(outputStream);
} catch (IOException e) {
e.printStackTrace();
}
只读集合创建
JAVA8 要创建一个只读不可改变的集合,要添加元素再通过unmodifiableList才能让集合变为只读集合。
List<String> list= new ArrayList<>();
list.add("Tom");
list.add("Jerry");
list = Collections.unmodifiableList(list);
System.out.println(list);
JAVA9 通过集合工厂方法,创建一个只读集合,只要通过新增的of方法即可完成创建.
public static void main(String[] args) {
List<String> list = List.of("张三", "李四", "王五");
System.out.println(list);
list.set(0,"aaa");
System.out.println(list);
}
同样的Set接口和Map接口下也新增了of方法,也是返回一个只读集合