javastring数组_Java String很简单?这6道面试题你试试!

对String不熟?请先看Java源码分析之String

来,请答题!

0. String,StringBuilder,StringBuffer的区别

StringBuffer和StringBuilder都实现了AbstractStringBuilder抽象类,拥有几乎一致对外提供的调用接口;其底层在内存中的存储方式与String相同,都是以一个有序的字符序列(char类型的数组)进行存储,不同点是StringBuffer/StringBuilder对象的值是可以改变的,并且值改变以后,对象引用不会发生改变;两者对象在构造过程中,首先按照默认大小申请一个字符数组,由于会不断加入新数据,当超过默认大小后,会创建一个更大的数组,并将原先的数组内容复制过来,再丢弃旧的数组。因此,对于较大对象的扩容会涉及大量的内存复制操作,如果能够预先评估大小,可提升性能。

唯一需要注意的是:StringBuffer是线程安全的,但是StringBuilder是「线程不安全」的。可参看Java标准类库的源代码,StringBuffer类中方法定义前面都会有synchronize关键字。为此,StringBuffer的性能要远低于StringBuilder。

1. "=="与equals()方法的区别

==:既可以比较基本数据类型,又可以比较引用数据类型。对基本数据类型,比较的是『』对引用数据类型,比较的是『地址』

equals()方法:只能比较引用数据类型. Java当中所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地址, 对于引用数据类型之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是基于他们在内存中的存放位置的地址值的。但在一些类库当中这个方法被覆盖掉了,如String, Integer, Date,在这些类当中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了。

下面的代码是String的equals()方法。先用==比较地址,地址相同则「字面值」一定相同。如果地址不同,其次比较「字面值」是否相等。

public 

注:8种基础数据类型为byte, short, char, int, long, float, double, boolean。引用数据类型例如 Integer, String等。

2. String s = new String("abc");定义了几个对象

背景知识:String的创建机理

由于String在Java世界中使用过于频繁,Java为了避免在一个系统中产生大量的String对象,引入了字符串常量池。其运行机制是:创建一个字符串时,首先检查池中是否有值相同的字符串对象,如果有则不需要创建直接从池中刚查找到的对象引用;如果没有则新建字符串对象,返回对象引用,并且将新创建的对象放入池中。

String s = new String("abc");定义了几个对象分两种情况。

  1. 若常量池中已经存在”abc”,则直接引用,也就是此时只会创建一个对象。
  2. 如果常量池中不存在”abc”,则先在常量池中创建后再引用,也就是创建了两个对象。

3. 如何理解String的intern()方法?

当一个String实例str调用intern()方法时,Java查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其的引用,如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用;

借Hollis的一张图说明三者的关系。

37f324e3312e2565916b9ae772cb8553.png

4. 判断以下输出的结果

public 

输出s1 == s2。s1="Monday"被放入常量池后,编译器发现s2="Monday"的值已经在常量值中,返回s1的引用给s2,即s1与s2有相同的地址,故s1 == s2。

public 

输出s3 != s4,s3 equals s4。第二段程序中,使用了 new 操作符,他明白的告诉程序:"我要一个新的!不要旧的!"于是一个新的"Monday"对象被创建在内存中。他们的值相同,但是位置不同, 一个在常量池,一个在堆(内存)中,所以 s3 != s4。equals()方法比较字面值,所以 s3.equals(s4)返回true。

public 

输出:s5 == s6。intern()检查字符串池里是否存在"Monday"这么一个字符串,如果存在,就返回池里的字符串;如果不存在,该方法会把"Monday"添加到字符串池中,然后再返回它的引用。s6.intern()返回了s5在常量池中的地址给s6。

5. 说说String的不可变性

Java String 对象的不可变性指 String 对象一旦创建成功,就不能再对它进行改变。第一,String 类被 final 关键字修饰了,我们知道类被 final 修饰代表该类不可被继承。变量 char 数组也被 final+private 修饰,代表了 String 对象不可被更改。

Java 这样做的好处在哪里呢?

第一,保证 String 对象的安全性。假设 String 对象是可变的,那么 String 对象将可能被恶意修改。

第二,保证 hash 属性值不会频繁变更,确保了唯一性,使得类似 HashMap 容器才能实现相应的 key-value 缓存功能。

第三,可以实现字符串常量池。

不可变的主要作用在于当一个对象需要被多线程共享,并且访问频繁时,可以省略同步和锁等待的时间,从而大幅度提高系统性能。不可变模式是一个可以提高多线程程序的性能,降低多线程程序复杂度的设计模式。

这里附上一个你可能会想到的经典反例。

平常编程时,对一个 String 对象 str 赋值“hello”,然后又让 str 值为“world”,这个时候 str 的值变成了“world”。那么 str 值确实改变了,为什么我还说 String 对象不可变呢?

这是因为 str 只是 String 对象的引用,并不是对象本身。对象在内存中是一块内存地址,str 则是一个指向该内存地址的引用。所以在刚刚我们说的这个例子中,第一次赋值的时候,创建了一个“hello”对象,str 引用指向“hello”地址;第二次赋值的时候,又重新创建了一个对象“world”,str 引用指向了“world”,但“hello”对象依然存在于内存中。也就是说 str 并不是对象,而只是一个对象引用。真正的对象依然还在内存中,没有被改变。

http://weixin.qq.com/r/-kU0LDjEAmV9rXxP9xDs (二维码自动识别)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值