JDK8-17API的变化

API的变化

Optional类

JDK8的新特性

到目前为止,臭名昭著的空指针异常是导致Java应用程序失败的最常见原因。以前,为了解决空指针异常,Google在著名的Guava项目引入了Optional类,通过检查空值的方式避免空指针异常。受到Google的启发,Optional类已经成为Java 8类库的一部分。

Optional 类(java.util.Optional) 是一个容器类,它可以保存类型T的值,代表这个值存在。或者仅仅保存null,表示这个值不存在。如果值存在,则isPresent()方法会返回true,调用get()方法会返回该对象。

Optional提供很多有用的方法,这样我们就不用显式进行空值检测。

  • 创建Optional类对象的方法:

  • static Optional empty() :用来创建一个空的Optional实例

    • static Optional of(T value) :用来创建一个Optional实例,value必须非空
    • static Optional ofNullable(T value) :用来创建一个Optional实例,value可能是空,也可能非空
  • 判断Optional容器中是否包含对象:

    • boolean isPresent() : 判断Optional容器中的值是否存在
    • void ifPresent(Consumer consumer) :判断Optional容器中的值是否存在,如果存在,就对它进行Consumer指定的操作,如果不存在就不做
  • 获取Optional容器的对象:

  • T get(): 如果调用对象包含值,返回该值。否则抛异常。T get()与of(T value)配合使用

  • T orElse(T other) :orElse(T other) 与ofNullable(T value)配合使用,如果Optional容器中非空,就返回所包装值,如果为空,就用orElse(T other)other指定的默认值(备胎)代替

  • T orElseGet(Supplier other) :如果Optional容器中非空,就返回所包装值,如果为空,就用Supplier接口的Lambda表达式提供的值代替

  • T orElseThrow(Supplier exceptionSupplier) :如果Optional容器中非空,就返回所包装值,如果为空,就抛出你指定的异常类型代替原来的NoSuchElementException

	@Test
    public void test1(){
        String str = "hello";
        Optional<String> opt = Optional.of(str);
        System.out.println(opt);
    }
    @Test
    public void test2(){
        Optional<String> opt = Optional.empty();
        System.out.println(opt);
    }
    @Test
    public void test3(){
        String str = null;
        Optional<String> opt = Optional.ofNullable(str);
        System.out.println(opt);
    }
    @Test
    public void test4(){
        String str = "hello";
        Optional<String> opt = Optional.of(str);

        String string = opt.get();
        System.out.println(string);
    }
    @Test
    public void test5(){
        String str = null;
        Optional<String> opt = Optional.ofNullable(str);
//		System.out.println(opt.get());//java.util.NoSuchElementException: No value present
    }
    @Test
    public void test6(){
        String str = "hello";
        Optional<String> opt = Optional.ofNullable(str);
        String string = opt.orElse("atguigu");
        System.out.println(string);
    }
    @Test
    public void test7(){
        String str = null;
        Optional<String> opt = Optional.ofNullable(str);
        String string = opt.orElseGet(String::new);
        System.out.println(string);
    }
    @Test
    public void test8(){
        String str = null;
        Optional<String> opt = Optional.ofNullable(str);
        String string = opt.orElseThrow(()->new RuntimeException("值不存在"));
        System.out.println(string);
    }
    @Test
    public void test9(){
        String str = "Hello1";
        Optional<String> opt = Optional.ofNullable(str);
        //判断是否是纯字母单词,如果是,转为大写,否则保持不变
        String result = opt.filter(s->s.matches("[a-zA-Z]+"))
                .map(s -> s.toUpperCase()).orElse(str);
        System.out.println(result);
    }

这是JDK9-11的新特性

新增方法 描述 新增的版本
boolean isEmpty() 判断value是否为空 JDK 11
ifPresentOrElse(Consumer action, Runnable emptyAction) value非空,执行参数1功能;如果value为空,执行参数2功能 JDK 9
Optional or(Supplier> supplier) value非空,返回对应的Optional;value为空,返回形参封装的Optional JDK 9
Stream stream() value非空,返回仅包含此value的Stream;否则,返回一个空的Stream JDK 9
T orElseThrow() value非空,返回value;否则抛异常NoSuchElementException JDK 10

String存储结构和API变更

这是JDK9的新特性。

产生背景:

Motivation
The current implementation of the String class stores characters in a char array, using two bytes (sixteen bits) for each character. Data gathered from many different applications indicates that strings are a major component of heap usage and, moreover, that most String objects contain only Latin-1 characters. Such characters require only one byte of storage, hence half of the space in the internal char arrays of such String objects is going unused.

String类的当前实现将字符存储在一个字符数组中,每个字符使用两个字节(16位)。从许多不同应用程序收集的数据表明,字符串是堆使用的主要组成部分,而且大多数字符串对象只包含Latin-1字符。这样的字符只需要1字节的存储空间,因此这些字符串对象的内部字符数组中有一半的空间没有使用。

使用说明:

Description

We propose to change the internal representation of the String class from a UTF-16 char array to a byte array plus an encoding-flag field. The new String class will store characters encoded either as ISO-8859-1/Latin-1 (one byte per character), or as UTF-16 (two bytes per character), based upon the contents of the string. The encoding flag will indicate which encoding is used.

我们建议将String类的内部表示形式从UTF-16字符数组更改为字节数组加上编码标志字段。新的String类将根据字符串的内容存储编码为ISO-8859-1/Latin-1(每个字符1字节)或UTF-16(每个字符2字节)的字符。encoding标志表示使用哪种编码。

结论:String 再也不用 char[] 来存储啦,改成了 byte[] 加上编码标记,节约了一些空间。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    @Stable
    private final byte[] value;
	...
}

拓展:StringBuffer 与 StringBuilder

那StringBuffer 和 StringBuilder 是否仍无动于衷呢?

String-related classes such as AbstractStringBuilder, StringBuilder, and StringBuffer will be updated to use the same representation, as will the HotSpot VM’s intrinsic string operations.

与字符串相关的类,如AbstractStringBuilder、StringBuilder和StringBuffer,将更新为使用相同的表示形式,HotSpot虚拟机的内部字符串操作也将更新。

JDK11新特性:新增了一系列字符串处理方法

描述 举例
判断字符串是否为空白 " ".isBlank(); // true
去除首尾空白 " Javastack ".strip(); // “Javastack”
去除尾部空格 " Javastack “.stripTrailing(); // " Javastack”
去除首部空格 " Javastack ".stripLeading(); // "Javastack "
复制字符串 “Java”.repeat(3);// “JavaJavaJava”
行数统计 “A\nB\nC”.lines().count(); // 3

JDK12新特性:String 实现了 Constable 接口

String源码:

public final class String implements java.io.Serializable, Comparable<String>, CharSequence,Constable, ConstantDesc {

java.lang.constant.Constable接口定义了抽象方法:

public interface Constable {
	Optional<? extends ConstantDesc> describeConstable();
}

Java 12 String 的实现源码:

/**
 * Returns an {@link Optional} containing the nominal descriptor for this
 * instance, which is the instance itself.
 *
 * @return an {@link Optional} describing the {@linkplain String} instance
 * @since 12
 */
@Override
public Optional<String> describeConstable() {
	return Optional.of(this);
}

很简单,其实就是调用 Optional.of 方法返回一个 Optional 类型。

举例:

private static void testDescribeConstable() {
	String name = "尚硅谷Java高级工程师";
	Optional<String> optional = name.describeConstable();
	System.out.println(optional.get());
}

结果输出:

尚硅谷Java高级工程师

JDK12新特性:String新增方法

String的transform(Function)

var result = "foo".transform(input -> input + " bar");
System.out.println(result); //foo bar

或者

var result = "foo".transform(input -> input + " bar").transform(String::toUpperCase)
System.out.println(result); //FOO BAR

对应的源码:

/**
* This method allows the application of a function to {@code this}
* string. The function should expect a single String argument
* and produce an {@code R} result.
* @since 12
*/
public <R> R transform(Function<? super String, ? extends R> f) {
 return f.apply(this);
}

在某种情况下,该方法应该被称为map()。

举例:

private static void testTransform() {
	System.out.println("======test java 12 transform======");
	List<String> list1 = List.of("Java", " Python", " C++ ");
	List<String> list2 = new ArrayList<>();
	list1.forEach(element -> list2.add(element.transform(String::strip)
								  .transform(String::toUpperCase)
								  .transform((e) -> "Hi," + e))
				 );
	list2.forEach(System.out::println);
}

结果输出:

======test java 12 transform======
Hi,JAVA
Hi,PYTHON
Hi,C++

如果使用Java 8的Stream特性,可以如下实现:

private static void testTransform1() {
        System.out.println("======test before java 12 ======");
        List<String> list1 = List.of("Java  ", " Python", " C++ ");

        Stream<String> stringStream = list1.stream().map(element -> element.strip()).map(String::toUpperCase).map(element -> "Hello," + element);
        List<String> list2 = stringStream.collect(Collectors.toList());
        list2.forEach(System.out::println);
    }

JDK17:标记删除Applet API

Applet API 提供了一种将 Java AWT/Swing 控件嵌入到浏览器网页中的方法。不过,目前 Applet 已经被淘汰。大部分人可能压根就没有用过 Applet。

Applet API 实际上是无用的,因为所有 Web 浏览器供应商都已删除或透露计划放弃对 Java 浏览器插件的支持。Java 9 的时候,Applet API 已经被标记为过时,Java 17 的时候终于标记为删除了。

具体如下:

java.applet.Applet
java.applet.AppletStub
java.applet.AppletContext
java.applet.AudioClip
javax.swing.JApplet
java.beans.AppletInitializer

你可能感兴趣的:(学习小结,java)