文章目录
- 语法层次改变
- 钻石操作符号语法升级
- try结构语法升级
- 下划线命名标识符的使用限制
- API层次的改变
- 接口中的私有方法
- String底层存储结构变化
- Stream新增4个API
- InputStream新增transferTo方法
- 只读集合创建
语法层次改变
钻石操作符号语法升级
钻石操作符,就是我们泛型使用的符号<>
JAVA8 中,匿名内部类不能使用钻石操作符,如下代码在JAVA8 中是报错的,匿名内部类这里不支持泛型推断,重写的方法不明确泛型
这里匿名内部类中的<>号里必须要和前面的声明保持一致,不能空着不写,这样重写的方法就根据匿名内部类的泛型
但是这种写法在JAVA9 中就允许了
而且在JAVA9中,匿名内部类的语法不仅仅可以用于接口和抽象类,普通类也可以通过匿名内部类写法,在某个实例上完成对某个方法的重写
public class Demo1 {public static void main(String[] args) {/** 匿名内部类仅仅在接口和抽象类上使用,作为一种快速的实现方式* JAVA9中,普通类也可以借助这种语法形式实现对方法的快速临时的重写* */Person<String> person=new Person<>(){@Overridepublic 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,返回一个只有一个元素的StreamStream<Integer> stream3 = Stream.ofNullable(null);}
iterate指定种子数、指定条件和迭代方式来获取流
public static void testNewIterate(){//JAVA8通过 generate方法获取一个StreamStream.generate(Math::random).limit(10).forEach(System.out::println);//JAVA8 通过iterate获取一个StreamStream.iterate(0,t-> t+2).limit(10).forEach(System.out::println);//JAVA9通过重载iterate获取StreamStream.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方法获取一个StreamStream<List<Integer>> stream = optional.stream();// 以为内部的每个元素也是一个List,通过flatMap方法,将内部的List转换为Stream后再放入一个大Streamstream.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方法,也是返回一个只读集合