1、什么是String,它是什么数据类型?
答:String是定义在java.lang包下的一个类,它不是基本数据类型。
String是不可变的,JVM使用字符串池来储存所有的字符串对象。
2、创建String对象的不同方式有哪些?
答:两种方式。分别是常量池创建与new对象创建
方式一 String s1 = “abc”;
方式二 String s2 = new String(“abc”);
方式一:在创建的时候JVM会先在字符串常量池中检索字符串内容是否存在,若存在则直接返回对应的引用,若不存在则在堆中创建一个String对象,假如其值为abc,同时将该对象的引用缓存在字符串常量池中以便以后重用,接着返回该对象的引用给s1。
方式二:在创建的时候会先在堆中创建一个String对象,假如其值为abc,接着返回该对象的引用给s2。
原理:
采用直接赋值的方式创建一个字符串时,假如创建采用这种方法创建一个字符串abc, JVM首先会去字符串池中查找是否存在"abc"这个对象,如果不存在,则在字符串常量池中创建"abc"这个对象,然后将池中"abc"这个对象的引用地址返回给字符串常量str,这样str会指向池中"abc"这个字符串对象;如果存在,则不创建任何对象,直接将池中"abc"这个对象的地址返回,赋给字符串常量。
采用new关键字新建一个字符串对象时,JVM首先在字符串池中查找有没有"abc"这个字符串对象,如果有,则不在池中再去创建"abc"这个对象了,直接在堆中创建一个"abc"字符串对象,然后将堆中的这个"abc"对象的地址返回赋给引用str,这样,str就指向了堆中创建的这个"abc"字符串对象;如果没有,则首先在字符串池中创建一个"abc"字符串对象,然后再在堆中创建一个"abc"字符串对象,然后将堆中这个"abc"字符串对象的地址返回赋给str引用,这样,str指向了堆中创建的这个"abc"字符串对象。
3、String三大特性
不变性: 是一个 immutable 模式的对象,不变模式的主要作用是当一个对象需要被多线程共享并频繁访问时,可以保证数据的一致性。
常量池优化: String 对象创建之后,会在字符串常量池中进⾏行缓存,下次创建同样的对象时,会直接返回缓存的引用。
final: String 类不可被继承,提⾼了系统的安全性。
3-1-1、说说你理解的字符串的不变性
字符串的不可变性是指通过 String 的方法来修改字符串都会产出新的字符串,但并非指字符串的字符一定无法被修改,我们可以通过反射一样可以对字符串的“状态/值” 进行修改。
另外字符串对象是不可变的。因为这样可以保证多个引用可以同时指向字符串池中的同一个对象。如果字符串是可变的,那么一个引用操作改变了对象的值,对其他引用会有影响,这样显然是不合理的。
3-1-2、不可变性的好处
1.3.1 节省内存
由于字符串的不可变性,不同的字符串变量可以引用同一个示例来实现节省堆内存的目的。
1.3.2 更安全
字符串的不可变性也保证了多线程访问时的线程的安全性。
1.3.3 hashCode 缓存
String 的 hashCode 的计算和构成字符串的字符有关,由于 String 的不可变性就可以将 hashCode 缓存起来。源码中也可以看出计算过之后,下次调用 hashCode 直接返回。
3-2、什么是字符串常量池?
方式1:
Java的字符串常量池是JVM专门指定的特殊内存区域,用来存储字符串字面量。在Java7之前,分配在JVM的方法区中,属于常量池的一部分。在Java7之后字符串常量池被移到堆内存中,以便JVM进行垃圾回收。
方式2:
字符串常量池位于堆内存中,专门用来存储字符串常量,可以提高内存的使用率,避免开辟多块空间存储相同的字符串,在创建字符串时 JVM 会首先检查字符串常量池,如果该字符串已经存在池中,则返回它的引用,如果不存在,则实例化一个字符串放到池中,并返回其引用。
4、String 是线程安全的吗?
String 是不可变类,一旦创建了String对象,我们就无法改变它的值。因此,它是线程安全的,同一个字符串实例可以被多个线程共享,保证了多线程的安全性。
5、在使用 HashMap 的时候,用 String 做 key 有什么好处?
HashMap 内部实现是通过 key 的 hashcode 来确定 value 的存储位置,而因为字符串是不可变的,当创建字符串时,它的 hashcode 被缓存下来,不需要再次计算,所以相比于其他对象更快。
6、面试题:String、StringBuffer、StringBuilder的区别与联系
(1)相同点:首先说一下相同点:String、StringBuffer 与 StringBuilder 都可以对字符串进行操作。
(2)效率:在字符串操作效率上看 StringBuilder > StringBuffer > String
(3)效率的区别分析:
String 在设计的时候处于安全和性能的考虑,设置为 final 修饰,长度不可变,每次在常量池新增一个字符串都是重新 new 一个对象,原来的对象没有引用后等待 GC 回收,所以效率比较慢。StringBuilder 和 StringBuffer 都是可变长度的字符串,都继承了 AbstractStringBuilder 。那么造成它们使用区别的原因分析源码可以知道。StringBuffer 的方法都加了 synchronized 同步锁,代表线程安全。而StringBuilder 则没有加锁,所以 StirngBuilder 的效率要优于 StirngBuffer。
(4)三者的使用场景总结:
如果要操作少量的数据用 = String
单线程操作字符串缓冲区 下操作大量数据 = StringBuilder(线程非安全)
多线程操作字符串缓冲区 下操作大量数据 = StringBuffer(有buff就是安全,这个是线程安全的)
(5)使用 StirngBuilder/StringBuffer 的建议 :
StirngBuilder/StringBuffer 的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再 丢弃旧的数组。在大多数情况下,你可以在创建 StirngBuilder/StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。
如:StringBuffer buffer = new StringBuffer(1000);
6、Java 中操作字符串都有哪些类?它们之间有什么区别?
操作字符串的类有:String、StringBuffer、StringBuilder。
String 和 StringBuffer、StringBuilder 的区别在于 String 声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象,而 StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。
StringBuffer 和 StringBuilder 最大的区别在于,StringBuffer 是线程安全的,而 StringBuilder 是非线程安全的,但 StringBuilder 的性能却高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。
7、 String 属于基础的数据类型吗?
String 不属于基础类型,基础类型有 8 种:byte、boolean、char、short、int、float、long、double,而 String 属于对象。
8. String str="i"与 String str=new String(“i”)一样吗?
不一样,因为内存的分配方式不一样。String str="i"的方式,Java 虚拟机会将其分配到常量池中;而 String str=new String("i") 则会被分到堆内存中。
9. 如何将字符串反转?
使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。
示例代码:
// StringBuffer reverse
StringBuffer stringBuffer = new StringBuffer();
stringBuffer. append("abcdefg");
System. out. println(stringBuffer. reverse()); // gfedcba
// StringBuilder reverse
StringBuilder stringBuilder = new StringBuilder();
stringBuilder. append("abcdefg");
System. out. println(stringBuilder. reverse()); // gfedcba
10. String 类的常用方法都有那些?
indexOf():返回指定字符的索引。
charAt():返回指定索引处的字符。
replace():字符串替换。
trim():去除字符串两端空白。
split():分割字符串,返回一个分割后的字符串数组。
getBytes():返回字符串的 byte 类型数组。
length():返回字符串长度。
toLowerCase():将字符串转成小写字母。
toUpperCase():将字符串转成大写字符。
substring():截取字符串。
equals():字符串比较。
join: 经常需要将一个数组或者List的各项通过分隔符连接成字符串时,常用此方法
format: String类的format()方法用于创建格式化的字符串以及连接多个字符串对象。熟悉C语言应该记得C语言的sprintf()方法,两者有类似之处。format()方法有两种重载形式。
(1) 使用当前本地区域对象(Locale.getDefault()),制定字符串格式和参数生成格式化的字符串
String String.format(String fmt, Object... args);
(2)自定义本地区域对象,制定字符串格式和参数生成格式化的字符串
String String.format(Locale locale, String fmt, Object... args);
**j11、ava中面试常见问题之String、StringBuffer和StringBuilder的区别**
java中提供三个类String、StringBuffer和StringBuilder来表示和操作字符串。字符串就是多个字符的集合。那么,他们之间有什么区别呢?
当面试官问到这个问题时,可以从以下3个方面来回答:
1,首先从速度上来说,StringBuilder>StringBuffer>String。
接下来解释为什么String速度最慢。因为String是内容不可变的,它的底层使用了一个不可变的数组private final char value[];因此不能用来拼接字符串;
而StringBuffer和StringBuilder都是内容可变的。底层使用的是可变的字符数组char[] value;(没有使用final来修饰)。可以用来拼接字符串。
2,从线程安全来说,因为String是不可被继承的,所以不可改变,故是线程安全的;StringBuffer是线程安全的;StringBuilder是线程不安全的。
3,适用场景:
String适用于少量字符串操作的情况;
StringBuffer适用于多线程下大量字符串操作的场景;
StringBuilder适用于单线程下大量字符串操作的场景