JAVA基础面试题

本文介绍了Java中的值传递和引用传递概念,详细讲解了String为何不可变的原因,包括字符串常量池、安全性、哈希值缓存和性能优化。此外,还对比了String、StringBuffer和StringBuilder的区别,以及分析了new String("abc")创建对象的数量,最后阐述了字符串常量池的作用。
摘要由CSDN通过智能技术生成

1.什么是值传递和引用传递?


值传递:传递对象的一个副本,即使副本被改变,也不会影响源对象,因为值传递的时候,实际上是将实参的值复制一份给形参。
引用传递:传递的并不是实际的对象,而是对象的引用,外部对引用对象的改变也会反映到源对象上,因为引用传递的时候,实际上是将实参的地址值复制一份给形参。
说明:对象传递(数组、类、接口)是引用传递,原始类型数据(整形、浮点型、字符型、布尔型)传递是值传递。

2.String为什么不可变?


2.1 先看看什么是不可变的对象。
如果一个对象,在它创建完成之后,不能再改变它的状态,那么它就是不可变的。不能改变状态的意思是,不能改变对象内的成员变量,
包括基本数据类型的值不能改变,引用类型的变量不能指向其他对象,引用类型指向的对象的状态也不能改变。

String 被设计成不可变的主要有以下几个原因:
2.1 字符串常量池
在 Java 中,存在一个字符串常量池(String Pool),它是存储字符串对象的特殊内存区域。当我们创建一个字符串时,如果该字符串已经存在于字符串常量池中,那么就会直接返回这个字符串的引用;
如果不存在,则会将该字符串添加到字符串常量池中,并返回新创建的字符串的引用。
由于字符串常量池的存在,多个字符串可以共享同一个实例,这样可以节省内存空间。而如果 String 是可变的,那么在修改字符串时,可能会导致其他使用相同字符串的地方出现问题。

2.2 安全性
由于 String 是不可变的,所以它在多线程环境下是安全的。多个线程可以同时访问和共享同一个字符串对象,而无需担心数据的修改问题。

2.3 缓存哈希值
String 类重写了 hashCode()方法,并且在第一次调用时计算并缓存了字符串的哈希值。由于 String 是不可变的,所以可以保证哈希值的唯一性和一致性。

2.4 性能优化
由于 String 是不可变的,所以可以进行一些性能优化。例如,在字符串拼接时,如果使用 StringBuilder 或 StringBuffer 来处理可变字符串,会比直接修改 String 对象的方式更高效。

既然String是不可变的,它内部还有很多substring,replace,replaceAll等这些操作的方法,这些方法好像会改变String对象,怎么解释?
其实不是,我们每次调用replace等方法,其实会在堆内存中创建了一个新的对象,然后其value数组引用指向不同的对象。

3.String,StringBuffer和StringBuilder的区别?


3.1.可变性
String不可变
StringBuffer和StringBuilder可变

3.2.线程安全
String不可变,是线程安全的
StringBuilder不是线程安全的
StringBuffer是线程安全的,内部使用synchronized进行同步

4.new String("abc")会创建几个对象?


使用这种方式会创建两个字符串对象(前提是字符串常量池中没有"abc"这个字符串对象)。
4.1."abc"属于字符串字面量,因此编译时期会在字符串常量池中创建一个字符串对象,指向这个"abc"字符串字面量;
4.2.使用new方式会在堆中创建一个字符串对象。

5.什么是字符串常量池?


字符串常量池保存着所有字符串字面量,这些字面量字编译时期就确定了。字符串常量位于堆内存中,专门用来存储字符串常量。
在创建字符串时,JVM首先会检查字符串常量池,如果该字符串已经存在池中,则返回其引用,如果不存在,则创建此字符串并放入池中,并返回其引用。

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值