真实用 javap 反编译传统 switch 语句和 switch 表达式(箭头语法),证明两者底层都真实编译成同一个 lookupswitch 指令,新语法没有引入新的字节码机制;真实反编译 String 类型的 switch,证明它是 hashCode() 定位 + equals() 校验的两段式 lookupswitch。
真实复现 ArrayList 遍历中结构性修改抛出 ConcurrentModificationException;真实复现一个经典陷阱:移除倒数第二个元素时因为 hasNext() 提前返回 false,异常真实没有抛出,留下静默的逻辑 bug;真实验证 CopyOnWriteArrayList 遍历用的是创建迭代器那一刻的快照。
真实验证 WeakReference 只要发生一次 GC 就会被回收,而 SoftReference 在内存充足时真实挺过普通 GC;真实用 -Xmx128m 制造内存压力,往 SoftReference 列表里塞 10万个 1MB 对象,观察真实有多少被回收;真实验证 ReferenceQueue 拿到的就是同一个引用对象本身。
真实反射验证匿名内部类确实存在一个隐藏的 this$0 字段指向外部实例;真实用 WeakReference 追踪外部对象的 GC 情况,发现即使清空了持有它的集合,只要方法帧里还有对外部对象的局部变量引用,GC 也不会立刻回收它,这个现象甚至和是否被匿名类捕获无关。
真实验证 Dog[] 可以赋值给 Animal[](数组协变),但往里面塞一个 Cat 会真实触发运行时 ArrayStoreException;真实验证 Object[] 指向 String[] 时塞 Integer 同样触发;真实验证 System.arraycopy() 同样受这个运行时类型检查约束,不会绕过。
真实验证字面量字符串默认进入常量池、new String() 不会进池、编译期常量拼接会被折叠进池而运行时拼接不会;真实验证 intern() 把字符串登记进常量池并返回池中引用;20万次不同字符串 intern() 的真实耗时数据。
真实反射验证 List<String> 和 List<Integer> 的 getClass() 结果完全相同,泛型参数在运行时确实不存在;真实用反射绕过泛型检查往容器里塞错误类型,证明 checkcast 插在每一个方法调用点本身,不是赋值处;真实验证泛型数组 List<String>[] 的运行时元素类型并没有被擦除,依然会触发 ArrayStoreException。
真实验证 try 主体正常执行完、只有 close() 抛异常的场景:调用方真实 catch 到的就是 close() 直接抛出的那个异常本身,getSuppressed() 真实是空数组,不是被包进了谁的 suppressed 里——因为这时候没有更值得优先报告的主异常,close() 的异常本身就真实升级成了主异常。对照 try 主体也抛异常的场景,close() 的异常这才真实变成 suppressed。第三组验证两个资源都在 close() 抛异常时,真实是最后关闭的那个变成主异常。
真实捕获 parallelStream 处理 1 万个元素时真实用到的所有线程名,结果是 10 个线程(9 个 ForkJoinPool.commonPool 工作线程 + main 线程本身),真实验证 main 线程也真实参与了计算,不是完全外包给线程池;对照普通 stream() 真实只用了 main 一个线程。真实计时一个 2000 万元素的平方和任务,预热后并行版本真实比串行快了约 4.48 倍。
真实验证只声明 map 不调用终端操作,map 里的打印语句真实一行都不会执行;调用 count() 之后真实检查,发现依然没有任何打印——不是因为惰性求值按元素延迟执行,而是 JDK 真实做了更彻底的优化:count() 在能确定元素个数不会变的场景下,直接跳过整个 map 逻辑。真实验证 findFirst() 的短路特性:处理到第 4 个元素满足条件就真实停止,不会处理完全部 10 个。
两个不同实例并发调用各自的 synchronized 实例方法,真实总耗时约 503ms,证明真实并行、互不阻塞;换成两次并发调用同一个 static synchronized 方法,哪怕通过不同实例发起调用,真实总耗时约 1008ms,证明真实互相阻塞,共享同一把类级别的锁;第三组真实验证:一个线程持有某个实例的对象锁忙着的时候,另一个线程调用这个类的 static synchronized 方法真实完全不受影响。
一个线程调用 synchronized 方法(锁住 this)期间真实 sleep 500ms,另一个线程紧接着调用 synchronized(this) 块版本的方法,真实测出等待了约 808ms(500ms 排队 + 300ms 自己执行),证明两者真实抢的是同一把对象锁;反过来用 synchronized 方法去等一个 synchronized(this) 块持有的锁,真实测出同样约 805ms 的等待,验证 synchronized 方法本质上就是对整个方法体包一层 synchronized(this)。