Java字符串面试题

1、下面程序的运行结果是什么?

String s1 = "java";
StringBuffer s2 = new StringBuffer(s1);
System.out.println(s1.equals(s2));      //1

StringBuffer s3 = new StringBuffer("java");
System.out.println(s3.equals("java"));      //2
System.out.println(s3.toString().equals(s1));       //3
  1. 注释 1 打印为 false,主要考察 String 的 equals 方法,String 源码中 equals 方法有对参数进行 instance of String 判断语句,
    StringBuffer 的祖先为 CharSequence,所以不相等。
  2. 注释 2 打印为 false,因为 StringBuffer 没有重写 Object 的 equals 方法,所以 Object 的 equals 方法实现是 == 判断,故为 false。
  3. 注释 3 打印为 true,因为 Object 的 toString 方法返回为 String 类型,String 重写了 equals 方法实现为值比较。

2、String、StringBuffer、StringBuilder 的区别是什么?

  1. String 是字符串常量,StringBuffer 和 StringBuilder 都是字符串变量,后两者的字符内容可变,而前者创建后内容不可变。
  2. StringBuffer是线程安全的,而StringBuilder是非线程安全的,线程安全会带来额外的系统开销,所以StringBuilder的效率比 StringBuffer高;
  3. String的每次修改操作都是在内存中重新 new 一个对象出来,而StringBuffer、StringBuilder则不用,且提供了一定的缓存功能,默认16个字节数组的大小,超过默认的数组长度时扩容为原来字节数组的长度 * 2 + 2,所以使用StringBuffer和StringBuilder 时可以适当考虑下初始化大小,以便通过减少扩容次数来提高代码的高效性。

StringBuffer的扩容机制?

3、怎样将 GB2312 编码的字符串转换为 ISO-8859-1 编码的字符串?

如下代码即可实现。2处打印为乱码,因为编码字符集和解码字符集不一样导致的。

String s1 = "哈喽";
System.out.println(s1);     //1,哈喽
String s2 = new String(s1.getBytes("GB2312"),"ISO-8859-1");     //2,¹þà¶
System.out.println(s2);

4、String 为什么是不可变的?

  1. String 不可变是因为在 JDK 中 String 类被声明为一个 final 类,且类内部的 value 字节数组也是 final 的。
  2. 只有当字符串是不可变时字符串池才有可能实现,字符串池的实现可以在运行时节约很多 heap 空间,因为不同的字符串变量都指向池中的同一个字符串。
  3. 因为字符串是不可变的,所以是多线程安全的,同一个字符串实例可以被多个线程共享,这样便不用因为线程安全问题而使用同步,字符串自己便是线程安全的。
  4. 因为字符串是不可变的所以在它创建的时候 hashcode 就被缓存了,不变性也保证了 hash 码的唯一性,不需要重新计算,这就使得字符串很适合作为 Map 的键,字符串的处理速度要快过其它的键对象,这就是 HashMap 中的键往往都使用字符串的原因。

5、说说 String str = "hello world"; 和 String str = new String("hello world"); 的区别?

  1. 在 java 的 class 文件中有专门的部分用来存储编译期间生成的字面常量和符号引用,这部分叫做 class 文件常量池,在运行期间对应着方法区的运行时常量池,所以 String str = "hello world"; 在编译期间生成了 字面常量和符号引用,运行期间字面常量 "hello world" 被存储在运行时常量池(只保存了一份)。
  2. 通过 new 关键字来生成对象是在堆区进行的,堆区进行对象生成的过程是不会去检测该对象是否已经存在的,所以通过 new 来创建的一定是不同的对象,即使字符串的内容是相同的。

6、下面程序的运行结果是什么?

String s1 = "java";
System.out.println("java" == s1.substring(0));  //1
System.out.println("ava" == s1.substring(1));   //2

substring方法的源码如下
根据传入的开始索引是否为0,来决定是返回当前对象还是新对象

public String substring(int beginIndex) {
    if (beginIndex < 0) {
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    int subLen = value.length - beginIndex;
    if (subLen < 0) {
        throw new StringIndexOutOfBoundsException(subLen);
    }
    return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}
  1. 注释1结果是true,因为传入0,所以返回当前对象,==比较的是地址,同一个对象的地址相等。
  2. 注释2结果是false,因为传入1,返回新对象,比较地址不相等。

7、下面程序的运行结果是什么?

String s1 = "JAVA";
String s2 = "java".toUpperCase();
System.out.println(s1==s2);         //1
System.out.println(s1.equals(s2));  //2
  1. 注释1结果为false,toUpperCase方法返回新字符串对象。
  2. 注释2结果为true,equals方法比较的是值。

8、下面程序的运行结果是什么?

String s1 = "JavaEE";
String s2 = "EE";
String s3 = "Java"+s2;
System.out.println(s1==s2); //1
  1. 注释1结果为false。字符串常量与字符串变量连接时得到的新字符串不再保存在常量池中,而是在堆内存中新建一个String对象来存放,很明显常量池中要求的存放的是常量,有String类型变量当然不能存在常量池中了。

9、下面程序的运行结果是什么?

String s1 = "javaEE";
final String s2 = "EE";
String s3 = "java"+s2;
System.out.println(s1 == s3);   //1
  1. 注释1的结果为true。此处是字符串常量与String类型常量连接,得到的新字符串依然保存在常量池中。
    因为对 final 变量的访问在编译期间都会直接被替代为真实的值。

10、下面程序的运行结果是什么?

private static String getMsg() {
    return "world";
}

String s1 = "helloworld";
final String s2 = getMsg();
String s3 = "hello" + s2;
System.out.println(s1 == s3);   //1
  1. final String s2 = getMsg() 其实与 final String s2 = new String(“world”) 是一样的,也就是说 return “world” 会在堆中创建一个 String 对象保存 ”world”。
  2. 虽然 s2被定义成了 final,但不代表是常量,因为虽然将 s2 用 final 修饰了,但是由于其赋值是通过方法调用返回的,那么它的值只能在运行期间确定,因此指向的不是同一个对象,所以可见并非定义为 final 的就保存在常量池中,很明显此处 s2 常量引用的 String 对象保存在堆中,因为 getMsg() 得到的 String 已经保存在堆中了,final 的 String 引用并不会改变 String 已经保存在堆中这个事实;对于 s2 换成 final String s2 = new String("world"); 一样会返回 false,原因同理。

11、下面程序的运行结果是什么?

String s1 = "javaEE";
String s2 = "java";
String s3 = "EE";
String s4 = s2+s3;
System.out.println(s4 == s1);                       //1、false
System.out.println(s4.intern() == s1);              //2、true
System.out.println(s4 == s1.intern());              //3、false
System.out.println(s4.intern() == s1.intern());     //4、true
  1. 注释1结果是false。因为s4指向堆内存中的字符串对象,而s1指向常量池中的字符串常量,两者的地址不相等。

12、为什么针对安全保密高的信息,char[] 比 String 更好?

  1. 因为 String 是不可变的,一旦创建就不能更改,直到垃圾收集器将它回收才能消失,即使我们修改了原先的变量,实际上也是在内存中新建一个对象,原数据还是保留在内存中等待回收。
  2. 而字符数组 char[] 中的元素是可以更改的,也就是说像密码等保密信息用完之后我们可以马上修改它的值而不留痕迹,从而相对于 String 有更好的安全性。

13、用 java 代码实现字符串的反转?

1、使用 JDK 中 StringBuffer(并发安全)或者 StringBuilder 的反转方法,不仅速度快、效率高,代码如下:

public static String reverse(String string){
    if (null ==string || string.length()<=1){
        return string;
    }
    return new StringBuffer(string).reverse().toString();
}

2、使用递归方案实现,代码如下:

public static String reverse(String string){
    if (null==string || string.length()<=1){
        return string;
    }
    return reverseOther(string.substring(1))+string.charAt(0);
}

14、用 java 代码来检查输入的字符串是否回文(对称)?

1、使用 JDK 现有 API 实现,代码如下:

public static boolean is(String string){
    if(string == null){
        return false;
    }
    StringBuilder reverse = new StringBuilder(string).reverse();
    return reverse.toString().equals(string);
}

2、自写判断算法

public static boolean is(String string){
    if(string == null){
        return false;
    }
    int length = string.length();
    for (int i = 0; i < length/2; i++) {
        if(string.charAt(i) != string.charAt(length-1-i)){
            return false;
        }
    }
    return true;
}

15、用 java 代码写一个方法从字符串中删除给定字符?

public static String remove(String string,char c){
    if (string == null){
        return null;
    }
    return string.replaceAll(Character.toString(c),"");
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,843评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,538评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,187评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,264评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,289评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,231评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,116评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,945评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,367评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,581评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,754评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,458评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,068评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,692评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,842评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,797评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,654评论 2 354

推荐阅读更多精彩内容