你真的了解String吗?一道面试题引发的思考

本文从一道面试题出发,探讨Java中String的不可变性。通过分析源码,揭示String被设计为不可变的原因,包括保证安全性、哈希码唯一性以及在常量池中的应用。此外,文章还列举了初级到高级的Java工程师面试题,涵盖阿里巴巴、美团和蚂蚁金服的面试真题,涉及JVM、MySQL、Redis等多个技术领域。
摘要由CSDN通过智能技术生成

前言

首先,先来和大家看一道熟悉的面试题,判断以下输出的结果分别是什么?

public class Test {
    public static void main(String[] args) {
        String str1 = "hello";
        String str2 = "hello";
        String str3 = new String("hello");
        String str4 = new String("hello");

        System.out.println(str1==str2);
        System.out.println(str1==str3);
        System.out.println(str3==str4);

        System.out.println(str1.equals(str2));
        System.out.println(str1.equals(str3));
        System.out.println(str3.equals(str4));
    }
} 

相信聪明的小伙伴们一定都知道正确输出是什么,没错,结果就是你们想的那样

true
false
false
true
true
true 

至于原因,因为equals比较的是两个对象的内容是否相等,显而易见,上面4个的内容都是hello,所以结果都是true
而==比较的则是对象的地址是否一致,我们知道,第一种方式String str1 = "hello",此种创建方式下,编译器首先检查常量池中是否含有此字符串常量,没有则创建,然后JVM会开辟一块堆内存存放一个隐式对象指向该字符串常量,接着在栈空间里创建str1变量,str1变量指向该块堆内存首地址。
第二种方式String str3 = new String("hello"),此种创建方式下,直接在堆内存new一个对象,并在常量池中创建“hello”字符串,该对象指向常量池中的“hello”字符串,然后创建str3变量,并将str3变量指向该块堆内存首地址。所以其实它们在内存中的分布是这样的 image.png 相信大家看到这里对上面的面试题应该就能理解了,接下来我们再聊聊String这个类的一些特性。

不可变?

打开String类的源码,可以看到这样一句话 image.png 这里已经明确说明,String类一旦创建就不会改变,原因也很简单,因为类被final修饰了 image.png 再来看下面一段代码

public class Test {
    public static void main(String[] args) {
        String a1 = new String("Hello");
        String a2 = new String("World");
        a1 += a2;
        System.out.println(a1);
    }
} 

此时输出的结果是HelloWorld,等等,不是刚说了String类是final修饰的,是不可变的么?怎么刚说完就又能变了呢?其实此段代码执行时,首先在内存中分配一块空间,它的大小为a1和a2空间大小之和,然后将a1和a2的内容复制到该内存空间相应位置,最后将变量a1指向该内存空间,此时的a1其实已经是一个新的String对象了。我们在阅读String中的方法是可以看出,所有的改变字符串的方法其实都是返回了一个新的对象return new String

原因

那么问题来了,为什么String会被设计成不可变的呢?主要原因有如下几点:

  1. 在Java程序中String类型是使用最多的,这就牵扯到大量的增删改查,每次增删改差之前其实jvm需要检查一下这个String对象的安全性,就是通过hashcode,当设计成不可变对象时候,就保证了每次增删改查的hashcode的唯一性,也就可以放心的操作。
  2. 网络连接地址URL,文件路径path通常情况下都是以String类型保存, 假若String不是固定不变的,将会引起各种安全隐患。就好比我们的密码不能以String的类型保存,,如果你将密码以明文的形式保存成字符串,那么它将一直留在内存中,直到垃圾收集器把它清除。而由于字符串被放在字符串缓冲池中以方便重复使用,所以它就可能在内存中被保留很长时间,而这将导致安全隐患
  3. 字符串值是被保留在常量池中的,也就是说假若字符串对象允许改变,那么将会导致各种逻辑错误。

最后

一直想整理出一份完美的面试宝典,但是时间上一直腾不开,这套一千多道面试题宝典,结合今年金三银四各种大厂面试题,以及 GitHub 上 star 数超 30K+ 的文档整理出来的,我上传以后,毫无意外的短短半个小时点赞量就达到了 13k,说实话还是有点不可思议的。

一千道互联网 Java 工程师面试题

内容涵盖:Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、Redis、MySQL、Spring、SpringBoot、SpringCloud、RabbitMQ、Kafka、Linux等技术栈(485页)

初级—中级—高级三个级别的大厂面试真题

阿里云——Java 实习生/初级

List 和 Set 的区别 HashSet 是如何保证不重复的

HashMap 是线程安全的吗,为什么不是线程安全的(最好画图说明多线程环境下不安全)?

HashMap 的扩容过程

HashMap 1.7 与 1.8 的 区别,说明 1.8 做了哪些优化,如何优化的?

对象的四种引用

Java 获取反射的三种方法

Java 反射机制

Arrays.sort 和 Collections.sort 实现原理 和区别

Cloneable 接口实现原理

异常分类以及处理机制

wait 和 sleep 的区别

数组在内存中如何分配

答案展示:

美团——Java 中级

BeanFactory 和 ApplicationContext 有什么区别

Spring Bean 的生命周期

Spring IOC 如何实现

说说 Spring AOP

Spring AOP 实现原理

动态代理(cglib 与 JDK)

Spring 事务实现方式

Spring 事务底层原理

如何自定义注解实现功能

Spring MVC 运行流程

Spring MVC 启动流程

Spring 的单例实现原理

Spring 框架中用到了哪些设计模式

为什么选择 Netty

说说业务中,Netty 的使用场景

原生的 NIO 在 JDK 1.7 版本存在 epoll bug

什么是 TCP 粘包/拆包

TCP 粘包/拆包的解决办法

Netty 线程模型

说说 Netty 的零拷贝

Netty 内部执行流程

答案展示:

蚂蚁金服——Java 高级

题 1:

  1. jdk1.7 到 jdk1.8 Map 发生了什么变化(底层)?

  2. ConcurrentHashMap

  3. 并行跟并发有什么区别?

  4. jdk1.7 到 jdk1.8 java 虚拟机发生了什么变化?

  5. 如果叫你自己设计一个中间件,你会如何设计?

  6. 什么是中间件?

  7. ThreadLock 用过没有,说说它的作用?

  8. Hashcode()和 equals()和==区别?

  9. mysql 数据库中,什么情况下设置了索引但无法使用?

  10. mysql 优化会不会,mycat 分库,垂直分库,水平分库?

  11. 分布式事务解决方案?

  12. sql 语句优化会不会,说出你知道的?

  13. mysql 的存储引擎了解过没有?

  14. 红黑树原理?

题 2:

  1. 说说三种分布式锁?

  2. redis 的实现原理?

  3. redis 数据结构,使⽤场景?

  4. redis 集群有哪⼏种?

  5. codis 原理?

  6. 是否熟悉⾦融业务?记账业务?蚂蚁⾦服对这部分有要求。

好啦~展示完毕,大概估摸一下自己是青铜还是王者呢?

前段时间,在和群友聊天时,把今年他们见到的一些不同类别的面试题整理了一番,于是有了以下面试题集,也一起分享给大家~

如果你觉得这些内容对你有帮助,可以加入csdn进阶交流群,领取资料

基础篇


JVM 篇


MySQL 篇



Redis 篇




由于篇幅限制,详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!

需要的小伙伴,可以一键三连,下方获取免费领取方式!
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图灵课堂诸葛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值