前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2019Java面试宝典基础篇 -- String类

2019Java面试宝典基础篇 -- String类

作者头像
浩Coding
发布2019-07-03 15:11:02
5300
发布2019-07-03 15:11:02
举报
文章被收录于专栏:浩Coding浩Coding

一、数组有没有 length属性?String 有没有 length() 方法?

数组有length 的属性。String 有 length()方法。JavaScript 中,获得字符串的长度是通过 length 属性得到的,这一点容易和 Java 混淆。

二、String 、StringBuilder 、StringBuffer 的区别?

Java 平台提供了两种类型的字符串: String 和 StringBuffer/StringBuilder,它们都可以储存和操作字符串,区别如下:

1)String 是只读字符串,String类是 final 类,不可以被继承。也就意味着 String 引用的字符串内容是不能被改变的。初学者可能会有这样的误解:

代码语言:javascript
复制
String str = “abc”;
str = “bcd”;

如上,字符串 str 明明是可以改变的呀!其实不然,str 仅仅是一个引用对象,它指向一个字符串对象“abc”。第二行代码的含义是让 str 重新指向了一个新的字符串“bcd”对象,而“abc”对象并没有任何改变,只不过该对象已经成为一个不可及对象罢了。

2)StringBuffer/StringBuilder 表示的字符串对象可以直接进行修改

3) StringBuilder 是 Java5 中引入的,它和 StringBuffer 的方法完全相同,区别在于它是在单线程环境下使用的,因为它的所有方法都没有被 synchronized 修饰,因此它的效率理论上也比 StringBuffer 要高。

三、什么情况下用“+”运算符进行字符串连接比调用 StringBuffer/StringBuilder对象的 append 方法连接字符串性能更好?

该题来自华为。

字符串是 Java 程序中最常用的数据结构之一。在 Java 中 String 类已经重载了"+"。也就是说,字符串可以直接使用"+"进行连接,如下面代码所示:

代码语言:javascript
复制
String str = "abc" + "edf";

但这样做真的好吗?当然,这个问题不能简单地回答 yes or no。要根据具体情况来定。在 Java 中提供了一个StringBuilder 类(这个类只在 J2SE5 及以上版本提供,以前的版本使用 StringBuffer 类),这个类也可以起到"+"的作用。那么我们应该用哪个呢?

下面让我们先看看如下的代码:

代码语言:javascript
复制
public class TestSimplePlus{
   public static void main(String[] args){
      String s = "abc";
      String ss = "ok" + s + "xyz" + 5;
      System.out.println(ss);
   }
}

上面的代码从表面上看,对字符串和整型使用"+"号并没有什么区别,但事实真的如此吗?下面让我们来看看这段代码的本质。

我们首先使用反编译工具(如 jdk 带的 javap、或 jad)将 TestSimplePlus 反编译成 Java Byte Code,其中的奥秘就一目了然了。在本文将使用 jad 来反编译,命令如下:

代码语言:javascript
复制
jad -o -a -s d.java TestSimplePlus.class

反编译后的代码如下:

读者可能看到上面的 Java 字节码感到迷糊,不过大家不必担心。本文的目的并不是讲解 Java Byte Code,因此,并不用了解具体的字节码的含义。使用 jad 反编译的好处之一就是可以同时生成字节码和源代码。这样可以进行对照研究。从上面的代码很容易看出,虽然在源程序中使用了"+",但在编译时仍然将"+"转换成 StringBuilder。因此,我们可以得出结论,

在 Java 中无论使用何种方式进行字符串连接,实际上都使用的是StringBuilder。

那么是不是可以根据这个结论推出使用"+"和 StringBuilder 的效果是一样的呢?这个要从两个方面的解释。如果从运行结果来解释,那么"+"和 StringBuilder 是完全等效的。但如果从运行效率和资源消耗方面看,那它们将存在很大的区别。当然,如果连接字符串行表达式很简单(如上面的顺序结构),那么"+"和 StringBuilder 基本是一样的,但如果结构比较复杂,如使用循环来连接字符串,那么产生的 Java Byte Code 就会有很大的区别。先让我们看看如下的代码:

代码语言:javascript
复制
String s = "";
Random rand = new Random();
for (int i = 0; i < 10; i++){
  s = s + rand.nextInt(1000) + " ";
}
System.out.println(s);

大家可以看到,虽然编译器将"+"转换成了 StringBuilder,但创建 StringBuilder 对象的位置却在 for 语句内部。这就意味着每执行一次循环,就会创建一个 StringBuilder 对象(对于本例来说,是创建了 10 个 StringBuilder对象),虽然 Java 有垃圾回收器,但这个回收器的工作时间是不定的。如果不断产生这样的垃圾,那么仍然会占用大量的资源。解决这个问题的方法就是在程序中直接使用 StringBuilder 来连接字符串,代码如下:

代码语言:javascript
复制
String s = "";
Random rand = new Random();
for (int i = 0; i < 10; i++){
  result.append(rand.nextInt(1000));
  result.append(" ");
}
System.out.println(s);

从上面的代码可以看出,创建 StringBuilder 的代码被放在了 for 语句外。虽然这样处理在源程序中看起来复杂,但却换来了更高的效率,同时消耗的资源也更少了。在使用 StringBuilder 时要注意,尽量不要"+"和 StringBuilder 混着用,否则会创建更多的 StringBuilder 对象。

StringBuffer 和 StringBuilder 的功能基本一样,只是StringBuffer 是线程安全的,而 StringBuilder 不是线程安全的。因此,StringBuilder 的效率会更高

四、String、StringBuffer、StringBuilder 的区别?

(1)、可变不可变

String:字符串常量,在修改时不会改变自身;若修改,等于重新生成新的字符串对象。

StringBuffer:在修改时会改变对象自身,每次操作都是对 StringBuffer 对象本身进行修改,不是生成新的对象;使用场景:对字符串经常改变情况下,主要方法:append(),insert()等。

(2)、线程是否安全

String:对象定义后不可变,线程安全。

StringBuffer:是线程安全的(对调用方法加入同步锁),执行效率较慢,适用于多线程下操作字符串缓冲区大量数据。

StringBuilder:是线程不安全的,适用于单线程下操作字符串缓冲区大量数据。

(3)、共同点

StringBuilder 与 StringBuffer 有公共父类 AbstractStringBuilder(抽象类)。

StringBuilder、 StringBuffer 的方法都会调用 AbstractStringBuilder 中的公共方法,如 super.append(...)。

只是 StringBuffer 会在方法上加 synchronized 关键字,进行同步。最后,如果程序不是多线程的,那么使用

StringBuilder 效率高于 StringBuffer。因此,StringBuilder 的效率会更高。

五、请写出下面程序的输出结果

代码语言:javascript
复制
String s1 = "Programming";
String s2 = new String("Programming");
String s3 = "Program"; 
String s4 = "ming"; 
String s5 = "Program" + "ming"; 
String s6 = s3 + s4; 
System.out.println(s1 == s2); //false
System.out.println(s1 == s5); //true
System.out.println(s1 == s6); //false
System.out.println(s1 == s6.intern());//true
System.out.println(s2 == s2.intern());//false

补充:解答上面的面试题需要知道如下两个知识点:

1. String 对象的 intern()方法会得到字符串对象在常量池中对应的版本的引用(如果常量池中有一个字符串与String 对象的 equals 结果是 true),如果常量池中没有对应的字符串,则该字符串将被添加到常量池中,然后返回常量池中字符串的引用;

2. 字符串的+操作其本质是创建了 StringBuilder 对象进行 append 操作,然后将拼接后的 StringBuilder 对象用 toString 方法处理成 String 对象,这一点可以用 javap -c StringEqualTest.class 命令获得 class 文件对应的 JVM 字节码指令就可以看出来。

六、String 是基本数据类型吗?

String 是引用类型底层用 char 数组实现的。

七、String 类常用方法

本系列Java面试题很多代码来自网络,后加上作者的修改。如有侵权,联系作者(公众号后台留言即可)马上删除。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 浩Coding 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档