`
uule
  • 浏览: 6342037 次
  • 性别: Icon_minigender_1
  • 来自: 一片神奇的土地
社区版块
存档分类
最新评论

[转]通过六个题目彻底掌握String

 
阅读更多

Java中String类由于其特殊性(不变类),几乎是笔试面试中的必考题,当然有些题目其实没啥意思,不过关键是要通过题目掌握原理性的东西。下面六道题目,如果您全部做对了,且明白其所以然,那么Java中的关于String的笔试面试题应该难不到你了。也许您觉得我说的有点过了,然而彻底明白这些题目,对理解String类还是很有好处的。
写出下面各题的打印输出的结果:

1

public static void main(String[] args){
	String a = "a1";
	String b = "a" + 1;
	System.out.println(a==b);
}

2

public static void main(String[] args){
	String a = "ab";
	String bb = "b";
	String b = "a" + bb;
	System.out.println(a==b);
}

3

public static void main(String[] args){
	String a = "ab";
	final String bb = "b";
	String b = "a" + bb;
	System.out.println(a==b);
}

4

public static void main(String[] args){
	String a = "ab";
	final String bb = getBB();
	String b = "a" + bb;
	System.out.println(a==b);
}
private static String getBB() { return "b"; }

5

private static String a = "ab";
public static void main(String[] args){
	String s1 = "a";
	String s2 = "b";
	String s = s1 + s2;
	System.out.println(s == a);
	System.out.println(s.intern() == a);
}

6

private static String a = new String("ab");
public static void main(String[] args){
	String s1 = "a";
	String s2 = "b";
	String s = s1 + s2;
	System.out.println(s == a);
	System.out.println(s.intern() == a);
	System.out.println(s.intern() == a.intern());
}

答案:

1)true

要说明一点:当两个字符串字面值连接时(相加),得到的新字符串依然是字符串字面值,保存在常量池中。

2)false

字符串常量String类型变量连接时,得到的新字符串不再保存在常量池中,而是在堆中新建一个String对象来存放。很明显常量池中要求的存放的是常量,有String类型变量当然不能存在常量池中了。

3)true

注意此题与上一题的区别,此处是字符串字面值与String类型常量连接,得到的新字符串依然保存在常量池中。

4)false

此题中第条语句:final String bb = getBB();其实与final String bb = new String(“b”);是一样的。也就是说return “b”会在堆中创建一个String对象保存”b”,虽然bb被定义成了final。可见并非定义为final的就保存在常量池中,很明显此处bb常量引用的String对象保存在堆中,因为getBB()得到的String已经保存在堆中了,final的String引用并不会改变String已经保存在堆中这个事实。

5)false,true

可能很多人对intern()这个函数不了解。JDK API文档中对intern()方法的描述是:

返回字符串对象的规范化表示形式。

一个初始为空的字符串池,它由类 String 私有地维护。

当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并返回此 String 对象的引用。

它遵循以下规则:对于任意两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true。

所有字面值字符串和字符串赋值常量表达式都使用 intern 方法进行操作。

上面字符串池即为字符串常量池。明白该题结果的原因了吧。

6)false,false,true

第五题看明白后,第六题就没什么好讲的了。

来源:http://itmian.com/2011/05/06/%e6%b7%b1%e5%85%a5%e7%90%86%e8%a7%a3javstring/

http://itmian.com/2011/05/05/six-string-interview-question-of-java/

 

 

String.intern(): 

  再补充介绍一点:存在于.class文件中的常量池,在运行期被JVM装载,并且可以扩充。

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

  示例: 

  String s0= "kvill"; 
  String s1=new String("kvill"); 
  String s2=new String("kvill"); 
  System.out.println( s0==s1 ); 
  System.out.println( "**********" ); 
  s1.intern(); 
  s2=s2.intern(); //把常量池中"kvill"的引用赋给s2 
  System.out.println( s0==s1); 
  System.out.println( s0==s1.intern() ); 
  System.out.println( s0==s2 ); 

 

结果:

 

false

**********

false

true

true

 

 

分析:

String x = "abc";
String y = new String("abcd");

 

 现在来分析一下内存的分配情况。如图:


 
可以看出,x与y存在栈中,它们保存了相应对象的引用。第一条语句没有在堆中分配内存,而是将“abc”保存在常量池中。对于第二条语句,同样会在常量池中有一个“abcd”的字符串,当new时,会拷贝一份该字符串存放到堆中,于是y指向了堆中的那个“abcd”字符串。不知道polaris有没有讲明白。如果您明白了,那么做前面那六道题就没什么问题了。

 

-----------------------------------------------------------------------------------------------------

StringBuffer、StringBuilder 与String的equal、== 比较值的区别:

String s = "abc";

StringBuilder s1 = new StringBuilder();
StringBuilder s2 = new StringBuilder();
s1.append(s);
s2.append(s);
System.out.println("s1.equals(s2):\t\t" + (s1.equals(s2)));
System.out.println("s1 == s2:\t\t" + (s1 == s2));
 
String s3 = s + "1";
String s4 = s + "1";
System.out.println("s3 == s4:\t\t" + (s3 == s4));
System.out.println("s3.equals(s4):\t\t" + (s3.equals(s4)));
 
Object obj1 = new Object();
Object obj2 = new Object();
System.out.println("obj1.equals(obj2):\t" + (obj1.equals(obj2)));
System.out.println("obj1 == obj2:\t\t" + (obj1 == obj2));

 

执行结果如下

s1.equals(s2): //     false
s1 == s2:     //  false
s3 == s4:     //  false
s3.equals(s4):   //   true
obj1.equals(obj2):  //false
obj1 == obj2:       //false

  有人说“==比较地址,equals比较内容”,从String的比较来看这是对的,但从上述StringBuilder来看,s1和s2的构造方式一模一样,其内容是相同的,但是equals的结果却是false,为何?

我们有必要看一下Object类的equals方法的实现:

public boolean equals(Object obj) {
    return (this == obj);
}

 Object中的equals就是用==来比较当前对象和传入的参数的。

再看看String的equals实现

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = count;
        if (n == anotherString.count) {
        char v1[] = value;
        char v2[] = anotherString.value;
        int i = offset;
        int j = anotherString.offset;
        while (n-- != 0) {
            if (v1[i++] != v2[j++])
            return false;
        }
        return true;
        }
    }
    return false;
}

 它去比较内容了。

再看StringBuilder,在其源码里没有发现equals方法,那么它就继承了Object的实现,用==来比较传进来的参数。

我们看到equals是个实例方法(非static),实例方法是可以被子类重写而去实现自己想要的行为的,因此,不能轻易的说equals就是比较内容的,其行为是特定于实现的。但==确实是比较地址的。因为java中不支持(至少现在不支持)运算符重载,我们不能改变==的含义,其行为是固定死的。

记得下次不要说“==比较地址,equals比较内容”这样的话了,如果要说,也在前面加上特定的条件,如“如果比较String”,勿断章取义

 

 

 

 

 

 

  • 大小: 7.7 KB
分享到:
评论

相关推荐

    List转换成String数组

    本文将详细介绍如何将一个`List<String>`类型的集合转换为`String[]`数组,并通过不同的方法来实现这一过程。这不仅有助于提高代码的可读性和效率,还能帮助开发者更好地理解和运用Java集合框架。 #### 一、背景...

    C#中char[]与string之间的转换 string 转换成 Char[]

    C#中char[]与string之间的转换可以通过使用ToCharArray()方法、string类的构造函数、StringBuilder的Append方法和string.Concat方法等方式来实现。同时,我们也可以使用Encoding类来将byte[]转换成string。

    HexString和Base64String的相互转换

    2. **Base64String转HexString**:这个过程首先对Base64字符串进行解码,还原成原始的二进制数据,然后再将这些二进制数据每字节拆分成两个十六进制字符,从而得到HexString。 在提供的`DataConvert.sln`和`...

    C# String 的各种转换

    ### C# String 的各种转换 在C#编程语言中,字符串与数字之间的转换是非常常见的操作。本文将详细介绍如何在C#中实现字符串与其他数据类型(如整数、浮点数等)之间的转换,并特别关注字符串与十六进制之间的转换。...

    JavaBean与JsonString的相互转换

    如果JsonString代表一个JsonArray,我们也可以将其转换为Java的集合类型,如List或ArrayList。以Jackson为例: ```java // 假设我们有一个JsonArray字符串 String jsonArrayString = "[{\"name\":\"John\"}, {\...

    c++中double与string相互转换算法

    在这个例子中,我们首先创建了一个`std::stringstream`对象`ss`,然后使用`运算符将`double`类型的`num`写入流中。最后,通过调用`str()`成员函数,我们可以获取存储在流中的字符串。 另一种方法是使用C++11引入的`...

    Android图片Bitmap和字符串String之间的相互转换

    通过阅读和学习这些代码,开发者可以更好地理解和掌握Bitmap与String转换的实践方法。 总之,Android开发中Bitmap与String之间的转换是图像处理的关键步骤,涉及图像的保存、传输和加载等多个环节。理解并熟练运用...

    各种string类型转换

    在IT领域,字符串类型转换是编程中非常基础且重要的部分,尤其在处理不同编码、数据类型转换时,掌握各种string类型的转换方法对于提高程序的健壮性和灵活性至关重要。以下将详细解析从给定文件中提取出的关于“各种...

    list转换成string数组

    下面我们将通过三个不同的示例来展示如何将`List<String>`转换为`String[]`数组。 ### 示例1:使用toArray方法 这是最简单也是最常用的转换方式,直接调用`List`的`toArray`方法即可完成转换。 ```java import ...

    c++ string转换double

    double strDou(std::string str) { // string转double char* ch = new char[str.length()]; double d; for (int i = 0; i != str.length(); i++) { ch[i] = str[i]; } d = atof(ch); return d; } ``` **1. ...

    java字符串与集合互相转换,字符串转List,Map,List转String,String转List源码

    List集合转换成String,String转List,Map转String,String转Map等 集合与字符串相互转换,可以自己扩展源码,带有注释

    分支与循环程序设计 将一个包含20个元素的数组STRING分成一个偶数数组STRING1和一个奇数数组STRING2

    在本实验中,我们将学习如何使用条件转移指令、串操作指令和循环指令来编写一个将一个包含20个元素的数组STRING分成一个偶数数组STRING1和一个奇数数组STRING2的程序。 二、实验要求 1. 掌握条件转移指令的使用...

    utf8与string的相互转换

    在计算机科学领域,字符编码是数据处理和存储中不可或缺的一部分,UTF-8和字符串(string)之间的转换是常见的操作。UTF-8是一种广泛使用的Unicode字符编码,它可以表示Unicode字符集中的所有字符,而字符串则通常指的...

    java中String类型转换方法.pdf

    Java 中 String 类型转换方法 Java 中 String 类型转换方法是一种常见的编程...Java 中 String 类型转换方法有多种形式,每种形式都有其特点和应用场景,掌握这些方法可以帮助开发者更好地进行数据类型之间的转换。

    BLOB与String互转

    最近开发遇到blob类型转换为String,一时犯难。所以总结了一段代码与之分享。亲测

    字符串数组转换成string类型的

    这些方法都是通过某种方式将数组中的每个元素连接起来,形成一个新的字符串。需要注意的是,不同的编程语言提供了不同的工具来处理字符串操作,选择哪种方法取决于具体的需求和性能考虑。在处理大量数据时,可能需要...

    java中Blob转String

    分享在JAVA中Blob转换成String实例

    文件转换(inputString)

    在这个场景中,"文件转换(inputString)"可能是指将一个字符串(String)形式的数据转换为InputStream对象,或者反过来,将InputStream对象转化为字符串。这通常发生在我们需要在网络上传输数据、存储数据或者在...

    文件与STRING互转

    一、文件转STRING 1. 文件读取:首先,我们需要读取文件的内容。在Python中,可以使用`open()`函数以二进制模式('rb')打开文件,然后使用`read()`方法获取文件的二进制数据。 ```python with open('filename', '...

    Android BCD和String的转换

    在Android开发中,有时我们需要处理二进制数据,特别是当涉及到通信...通过学习和分析这个项目,你将能更好地理解和掌握Android环境下BCD码与字符串之间的转换技巧,这对于处理通信协议、存储格式转换等场景大有裨益。

Global site tag (gtag.js) - Google Analytics