java中常见的关于String的题目

来源:互联网 发布:球球大作战辅助软件 编辑:程序博客网 时间:2024/04/30 10:05

在看题目之前,首先来看一张图片:


该图截自JDK API,相信大家已经看到我在图中用红色圈圈,圈出来的部分,对,String类是被定义为final的,是不可变类,本文不针对这点做过多阐述,有兴趣的可以参阅这篇文章:J2SE基础夯实系列之String字符串不可变的理解,不可变类,final关键字到底修饰了什么

       下面看一些具体的问题:

1.String s1 = "ab";

   String s2 = new String("ab");

   System.out.println(s1 == s2);

   System.out.println(s1.equals(s2));

这段代码的输出会是啥呢?

答案是:

false

true

这个问题首先要注意的是==与equals的区别

==是比较是s1与s2是否是同一个对象,上面的s1与s2不是同一个对象,s1的“ab”是在String pool中,而s2的“ab”是在堆中,二者并不是同一个对象,所以输出false

equals呢是比较s1与s2中的内容是否相同,显然二者相同,所以输出true


  1. 2.
  2. String s = new String("abc");   
  3. String s1 = "abc";   
  4. String s2 = new String("abc");   
  5.   
  6. System.out.println(s == s1);   
  7. System.out.println(s == s2);   
  8. System.out.println(s1 == s2);  
请问以上程序执行结果是什么? 

第一句执行后内存中有两个对象,而不是一个(可以参考这篇文章:java中String s = new String("abc")创建了几个对象?!)。一个由new String("abc")中的"abc"在String Pool里生成一个值为"abc"的对象;第二个由new在堆里产生一个值为"abc"的对象,该对象完全是String Pool里的"abc"的一个拷贝。变量s最后指向堆中产生的"abc"对象; 
第二句执行时,s1先去String Pool找是否有值为"abc"的对象,很显然在上一步中java已经在String Pool里生成一个"abc"对象了,所以s1直接指向String Pool中的这个"abc"; 
第三句中又有一个new,在java中凡遇到new时,都会在堆里产生一个新的对象。因此,该句执行后堆里又多了一个"abc"对象,这与执行第一句后生成的"abc"是不同的两个对象,s2最后指向这个新生成的对象。 
因此,执行后面的打印语句的结果是三个false 


3.

      String str1 = new String("abc");
      String str2 = new String("abc");
      if(str1 == str2)
      {
        System.out.println("str1 == str2");
      }
      if(str1.equals(str2))
      {
        System.out.println("str1 equals str2");
      }
      
      String str3 = "abc";
      String str4 = "abc";
      if(str3 == str4)
    {
      System.out.println("str3 == str4");
    }
    if(str3.equals(str4))
    {
      System.out.println("str3 equals str4");
    }
    if(str1 == str4)
    {
      System.out.println("str1 equals str4");
    }
    if(str1.equals(str4))
    {
      System.out.println("str1 equals str4");
    }
复制代码

 

运行结果为:

str1 equals str2
str3 == str4
str3 equals str4
str1 equals str4

为什么会出现这样的结果。。。这需要引入一些概念,其实很类似C++ 或C#之类,差别只是小小的。。。

首先了解一个对象在内存中创建的区域:

1.heap(即堆区):它是负责创建对象的,所有的创建出来的对象都是放在堆区的。所有new操作的创建的实例都存储在这里,包括用new String 创建的String。 
2.stack(即栈区):它是负责存放局部变量,和成员变量的。所有的成员变量和局部变  量都放在这个区内,然后他通过一个引用指向栈区的对象或data segment(静态代码)区的静态数据。
3.data segment(静态代码区):在这个区主要存放的是静态常量,和字符串常量(字符串池)。在类一开始被加载的时候此常量就被初始化放在这个区内,而且被全局所共享,所有的访问直接指向他即可。
4.code segment(代码区):它是存放代码的区,所有的执行代码都放在此区内。通过对象的调用指向此区。



4.String s = "a" + "b" + "c" + "d" + "e";问此语句共创建了几个对象

答案是:创建了一个对象

可以尝试运行这段程序

String s1 = "a";  String s2 = s1 + "b";  String s3 = "a" + "b";  System.out.println(s2 == "ab");  System.out.println(s3 == "ab");    String s = "a" + "b" + "c" + "d";  System.out.println(s == "abcd"); 

运行结果为:

  1. false  
  2. true  
  3. true

第一条语句打印的结果为false,第二条语句打印的结果为true,这说明javac编译可以对字符串常量直接相加的表达式进行优化,不必要等到运行期去进行加法运算处理,而是在编译时去掉其中的加号,直接将其编译成一个这些常量相连的结果。题目中的代码被编译器在编译时优化后,相当于直接定义了一个”abcd”的字符串,所以,题目中的代码应该只创建了一个String对象。

写如下两行代码,String s = "a" + "b" + "c" + "d";

System.out.println(s == "abcd");最终打印的结果应该为true


在文章最后贴上这些类型题目的一个代码^_^:

public class Test{    public static void main(String[] args){   String s1 = "a";   String s2 =  s1 +"b";   String s3 = "a" + "b";   System.out.println("s2 == \"ab\"  " + (s2 == "ab"));   System.out.println("s3 == \"ab\"  " + (s3 == "ab"));   String s4 = "ab";   String s5 = new String("ab");   String s6 = new String("ab");   System.out.println("s4 == s5  " + (s4 == s5));   System.out.println("s4.equals(s5)  " + (s4.equals(s5)));   System.out.println("s4 == s3  " + (s4 == s3));   System.out.println("s2 == s5  " + (s2 == s5));   System.out.println("s5 == s6  " + (s5 == s6));}}


输出结果是:


原创粉丝点击