java 11 新特性源码分析和使用

java 11 新特性源码分析和使用

Java 11 的一些重要功能包括:

  • 使用单个命令运行 Java 文件
  • String 类中的新实用程序方法
  • Lambda 参数的局部变量语法
  • 基于嵌套的访问控制
  • JEP 321:HTTP 客户端
  • 在文件中读取/写入字符串
  • JEP 328:飞行记录器

Java 字符串方法

isBlank() –此实例方法返回一个布尔值。空字符串和仅包含空格的字符串将被视为空白。

    public static void isBlank(){
        String out = "";
        String out1 = null;
        System.out.println(out.isBlank());
        System.out.println(out.isEmpty());
        //这里会抛出空指针异常
        System.out.println(out1.isBlank());
        System.out.println(out1.isEmpty());
    }

isBlank()和 isEmpty()之间的区别:

    public boolean isBlank() {
        return indexOfNonWhitespace() == length();
    }

    private int indexOfNonWhitespace() {
        if (isLatin1()) {
            return StringLatin1.indexOfNonWhitespace(value);
        } else {
            return StringUTF16.indexOfNonWhitespace(value);
        }
    }

isBlank()使用了两个方法来确定 String 是否为空字符串

但是首先我们要关注的 String 的声明方式

    String(byte[] value, byte coder) {
        this.value = value;
        this.coder = coder;
    }

每个 String 的构造函数是不必要的,因为字符串不可变,但是这里需要声明一个代表空字符的序列

再来看 isLation1()

    static final boolean COMPACT_STRINGS;

    static {
        COMPACT_STRINGS = true;
    }

    @Native static final byte LATIN1 = 0;

    private boolean isLatin1() {
        return COMPACT_STRINGS && coder == LATIN1;
    }

静态声明 COMPACT_STRINGS,但是 COMPACT_STRINGS 实在 jvm 启动时才被赋值,这样可能可以避免循环依赖

我对于这里的理解是当字符串被经禁止时,编码始终为 UTF16,但是为了 JIT 的效率,优化写法,所以此处 COMPACT_STRINGS 这样声明.
isLatin1()是为了判断编码格式为拉丁还是 UTF16

StringLatin1.indexOfNonWhitespace(value)

StringUTF16.indexOfNonWhitespace(value)

不管字符串的编码格式为什么,他们最终和 length()对比

    public int length() {
        return value.length >> coder();
    }

        byte coder() {
        return COMPACT_STRINGS ? coder : UTF16;
    }

字符串中的代码单位始终采用的是 UTF16

简单来说 isBlank()是一个判断字符串编码(LATIN1 和 UTF16)后获得 byte 长度,它们的对比对象都是 UTF16 的 byte 长度

相对来说 isEmpty()要简单得多

isEmpty()

    private final byte[] value;

    public boolean isEmpty() {
        return value.length == 0;
    }

它仅仅是建立了一个 byte[]用于字符存储,在它的源码上有一句话,’ because value is never null’因为

    public String() {
        this.value = "".value;
        this.coder = "".coder;
    }

但是,为什么我们在声明一个 String 为 null,会抛出空指针异常呢?我认为这个异常应该是没有找到这个字符串,而不是 String 类里面抛出的,我做了一个尝试,运行以下代码

把断点打在 isBlank()

这是报文

断点并没有进入到 isBlank(),证明 String 为 null,本身就无法调用到 String 中的方法

lines()返回从该字符串中提取的行流

    public static void lines() {
        String out = " \n n  \r r  \r\n rn ";
        System.out.println(out.lines().collect(Collectors.toList()));
    }

控制台输出

[ ,  n  ,  r  ,  ,  rn ]

此方法只能针对于换行符’\n’ , ‘\r’
它比 split(’\R’)更快地搜索新的行终止符

strip() 简单来说就是返回去掉空格的字符串

它和 trim()有什么不一定样呢,我们首先来看下代码输出

    public static void strip(){
        String str = " JD ";
        System.out.print("Start");
        System.out.print(str.strip());
        System.out.println("End");

        System.out.print("Start");
        System.out.print(str.stripLeading());
        System.out.println("End");

        System.out.print("Start");
        System.out.print(str.stripTrailing());
        System.out.println("End");
    }
StartJDEnd
StartJD End
Start JDEnd

最大的不一样 strip()可以选择去掉空格符分隔的数组头还是尾,

    public String strip() {
        String ret = isLatin1() ? StringLatin1.strip(value)
                                : StringUTF16.strip(value);
        return ret == null ? this : ret;
    }

同样的,java11 中对于字符串的操作几乎都判断了字符串的编码格式是 LATIN1 还是 UTF16

repeat()返回其值重复的字符串的串联字符串

通俗来说就是返回一个重复几次的字符串

    public static void repeat(){
        System.out.println("12".repeat(2));
    }
1212

当然这个会有最大重复限制,不过也和字符串的长度相关,可以在源码中找到

@Native public static final int   MAX_VALUE = 0x7fffffff;

public String repeat(int count) {
        if (count < 0) {
            throw new IllegalArgumentException("count is negative: " + count);
        }
        if (count == 1) {
            return this;
        }
        final int len = value.length;
        if (len == 0 || count == 0) {
            return "";
        }
        if (len == 1) {
            final byte[] single = new byte[count];
            Arrays.fill(single, value[0]);
            return new String(single, coder);
        }
        if (Integer.MAX_VALUE / count < len) {
            throw new OutOfMemoryError("Repeating " + len + " bytes String " + count +
                    " times will produce a String exceeding maximum size.");
        }
        final int limit = len * count;
        final byte[] multiple = new byte[limit];
        System.arraycopy(value, 0, multiple, 0, len);
        int copied = len;
        for (; copied < limit - copied; copied <<= 1) {
            System.arraycopy(multiple, 0, multiple, copied, copied);
        }
        System.arraycopy(multiple, 0, multiple, copied, limit - copied);
        return new String(multiple, coder);
    }

MAX_VALUE为2的31次方-1

Lambda参数的局部变量语法

用于声明隐式类型的lambda表达式的形式参数

    public static void lambda() {
        var list = new ArrayList<String>();
        //java11
        list.stream()
                .map((var s) -> s.toLowerCase())
                .collect(Collectors.toList());
        //java8
        list.stream()
                .map(String::toLowerCase)
                .collect(Collectors.toList());


    }

file读写

java从8开始就一直在简化文件的读写,对于开发者来说未尝不是一件好事.

    public static void file() throws IOException {
        Path path = Files.write(Files.createTempFile("test", ".txt"), Collections.singleton("公众号:java企业级应用"));
        System.out.println(path);
        String s = Files.readString(path);
        System.out.println(s); //This was posted on J
    }

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值