《从Java面试题看源码》-Java11中的toString与Java8的区别

简介: 《从Java面试题看源码》-Java11中的toString与Java8的区别

​​在这里插入图片描述
在前面【《从Java面试题来看源码》-LinkedBlockingQueue 源码分析】的文章中,我们看到有一个toString方法是这样的:

public String toString() {
    //
    return Helpers.collectionToString(this);
}

为什么要这样呢?

分析

`使用Helpers类,来输出字符串,与Java8不同。
Helpers类用于并发包输出字符串,该类只在输出数组的时候获取锁,而不是在toString中获取锁`

Java11中用到了Helpers.collectionToString(this)的方式输出字符串,并且与Java8是不同的。

先看看Java11中Helpers类的写法:

 /**
     * Collection.toString() 的一种实现,适用于有锁的类。
     * 代替了以前在整个toString()过程中加锁,或者在每次调用Iterator.next()的时候加锁
     * 该方法只在调用toArray()期间加锁,以减少其他线程对访问集合时产生的影响
     * 并且遵循在加锁期间,不调用任何外部代码
     */
static String collectionToString(Collection<?> c) {
    //这里toArray会加锁
    final Object[] a = c.toArray();
    final int size = a.length;
    if (size == 0)
        return "[]";
    int charLength = 0;

    // Replace every array element with its string representation
    for (int i = 0; i < size; i++) {
        Object e = a[i];
        // Extreme compatibility with AbstractCollection.toString()
        String s = (e == c) ? "(this Collection)" : objectToString(e);
        a[i] = s;
        charLength += s.length();
    }

    return toString(a, size, charLength);
}

/**
 * 与 Arrays.toString() 类似,但调用者保证 size > 0,索引为 0 <= i < size 的每
 * 个元素都是非空 String,charLength 是输入 String 的长度之和。
 */
static String toString(Object[] a, int size, int charLength) {
    // assert a != null;
    // assert size > 0;

    // Copy each string into a perfectly sized char[]
    // Length of [ , , , ] == 2 * size
    final char[] chars = new char[charLength + 2 * size];
    chars[0] = '[';
    int j = 1;
    for (int i = 0; i < size; i++) {
        if (i > 0) {
            chars[j++] = ',';
            chars[j++] = ' ';
        }
        String s = (String) a[i];
        int len = s.length();
        s.getChars(0, len, chars, j);
        j += len;
    }
    chars[j] = ']';
    // assert j == chars.length - 1;
    return new String(chars);
}

整个过程中就是将当前状态队列的元素进行拼接输出,而不会影响到其他线程操作队列,只是在通过toArray()获取队列元素的时候进行加锁。

看看Java8是怎么写的:

public String toString() {
    fullyLock();
    try {
        Node<E> p = head.next;
        if (p == null)
            return "[]";

        StringBuilder sb = new StringBuilder();
        sb.append('[');
        for (;;) {
            E e = p.item;
            sb.append(e == this ? "(this Collection)" : e);
            p = p.next;
            if (p == null)
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    } finally {
        fullyUnlock();
    }
}

Java8中,toString输出字符串在前面加了一个锁fullyLock(),fullyLock()使用ReentrantLock对put和take、poll分别加锁。

Java8会在整个toString的拼接过程中,对队列进行加锁,会影响性能。

private final ReentrantLock takeLock = new ReentrantLock();
private final ReentrantLock putLock = new ReentrantLock();
void fullyLock() {
    putLock.lock();
    takeLock.lock();
}

总结

简单点说

Java8中的toString,就如同一个人干活,一群人歇下来看着他干完完,比较粗暴。
在这里插入图片描述
Java11中是:

toString():我要输出了,队列你先把当前值给我

队列:放下原来的事,把toString()要的数据准备好,给了toString()后,继续做原来的事

toString:我可以输出了
在这里插入图片描述
我想这应该是很好理解的。

相关文章
|
10月前
|
缓存 Java 关系型数据库
2025 年最新华为 Java 面试题及答案,全方位打造面试宝典
Java面试高频考点与实践指南(150字摘要) 本文系统梳理了Java面试核心考点,包括Java基础(数据类型、面向对象特性、常用类使用)、并发编程(线程机制、锁原理、并发容器)、JVM(内存模型、GC算法、类加载机制)、Spring框架(IoC/AOP、Bean生命周期、事务管理)、数据库(MySQL引擎、事务隔离、索引优化)及分布式(CAP理论、ID生成、Redis缓存)。同时提供华为级实战代码,涵盖Spring Cloud Alibaba微服务、Sentinel限流、Seata分布式事务,以及完整的D
528 1
|
10月前
|
存储 安全 Java
常见 JAVA 集合面试题整理 自用版持续更新
这是一份详尽的Java集合面试题总结,涵盖ArrayList与LinkedList、HashMap与HashTable、HashSet与TreeSet的区别,以及ConcurrentHashMap的实现原理。内容从底层数据结构、性能特点到应用场景逐一剖析,并提供代码示例便于理解。此外,还介绍了如何遍历HashMap和HashTable。无论是初学者还是进阶开发者,都能从中受益。代码资源可从[链接](https://pan.quark.cn/s/14fcf913bae6)获取。
398 3
|
7月前
|
算法 Java
50道java集合面试题
50道 java 集合面试题
|
9月前
|
缓存 Java API
Java 面试实操指南与最新技术结合的实战攻略
本指南涵盖Java 17+新特性、Spring Boot 3微服务、响应式编程、容器化部署与数据缓存实操,结合代码案例解析高频面试技术点,助你掌握最新Java技术栈,提升实战能力,轻松应对Java中高级岗位面试。
609 0
|
9月前
|
Java 数据库连接 数据库
Java 相关知识点总结含基础语法进阶技巧及面试重点知识
本文全面总结了Java核心知识点,涵盖基础语法、面向对象、集合框架、并发编程、网络编程及主流框架如Spring生态、MyBatis等,结合JVM原理与性能优化技巧,并通过一个学生信息管理系统的实战案例,帮助你快速掌握Java开发技能,适合Java学习与面试准备。
401 2
Java 相关知识点总结含基础语法进阶技巧及面试重点知识
|
10月前
|
存储 安全 Java
2025 最新史上最全 Java 面试题独家整理带详细答案及解析
本文从Java基础、面向对象、多线程与并发等方面详细解析常见面试题及答案,并结合实际应用帮助理解。内容涵盖基本数据类型、自动装箱拆箱、String类区别,面向对象三大特性(封装、继承、多态),线程创建与安全问题解决方法,以及集合框架如ArrayList与LinkedList的对比和HashMap工作原理。适合准备面试或深入学习Java的开发者参考。附代码获取链接:[点此下载](https://pan.quark.cn/s/14fcf913bae6)。
5621 50
|
7月前
|
存储 小程序 Java
热门小程序源码合集:微信抖音小程序源码支持PHP/Java/uni-app完整项目实践指南
小程序已成为企业获客与开发者创业的重要载体。本文详解PHP、Java、uni-app三大技术栈在电商、工具、服务类小程序中的源码应用,提供从开发到部署的全流程指南,并分享选型避坑与商业化落地策略,助力开发者高效构建稳定可扩展项目。
|
7月前
|
算法 Java
50道java基础面试题
50道java基础面试题
|
10月前
|
算法 架构师 Java
Java 开发岗及 java 架构师百度校招历年经典面试题汇总
以下是百度校招Java岗位面试题精选摘要(150字): Java开发岗重点关注集合类、并发和系统设计。HashMap线程安全可通过Collections.synchronizedMap()或ConcurrentHashMap实现,后者采用分段锁提升并发性能。负载均衡算法包括轮询、加权轮询和最少连接数,一致性哈希可均匀分布请求。Redis持久化有RDB(快照恢复快)和AOF(日志更安全)两种方式。架构师岗涉及JMM内存模型、happens-before原则和无锁数据结构(基于CAS)。
276 5
下一篇
开通oss服务