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”,勿断章取义。
相关推荐
本文将详细介绍如何将一个`List<String>`类型的集合转换为`String[]`数组,并通过不同的方法来实现这一过程。这不仅有助于提高代码的可读性和效率,还能帮助开发者更好地理解和运用Java集合框架。 #### 一、背景...
2. **Base64String转HexString**:这个过程首先对Base64字符串进行解码,还原成原始的二进制数据,然后再将这些二进制数据每字节拆分成两个十六进制字符,从而得到HexString。 在提供的`DataConvert.sln`和`...
C#中char[]与string之间的转换可以通过使用ToCharArray()方法、string类的构造函数、StringBuilder的Append方法和string.Concat方法等方式来实现。同时,我们也可以使用Encoding类来将byte[]转换成string。
### C# String 的各种转换 在C#编程语言中,字符串与数字之间的转换是非常常见的操作。本文将详细介绍如何在C#中实现字符串与其他数据类型(如整数、浮点数等)之间的转换,并特别关注字符串与十六进制之间的转换。...
如果JsonString代表一个JsonArray,我们也可以将其转换为Java的集合类型,如List或ArrayList。以Jackson为例: ```java // 假设我们有一个JsonArray字符串 String jsonArrayString = "[{\"name\":\"John\"}, {\...
在这个例子中,我们首先创建了一个`std::stringstream`对象`ss`,然后使用`运算符将`double`类型的`num`写入流中。最后,通过调用`str()`成员函数,我们可以获取存储在流中的字符串。 另一种方法是使用C++11引入的`...
通过阅读和学习这些代码,开发者可以更好地理解和掌握Bitmap与String转换的实践方法。 总之,Android开发中Bitmap与String之间的转换是图像处理的关键步骤,涉及图像的保存、传输和加载等多个环节。理解并熟练运用...
在IT领域,字符串类型转换是编程中非常基础且重要的部分,尤其在处理不同编码、数据类型转换时,掌握各种string类型的转换方法对于提高程序的健壮性和灵活性至关重要。以下将详细解析从给定文件中提取出的关于“各种...
下面我们将通过三个不同的示例来展示如何将`List<String>`转换为`String[]`数组。 ### 示例1:使用toArray方法 这是最简单也是最常用的转换方式,直接调用`List`的`toArray`方法即可完成转换。 ```java import ...
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. ...
List集合转换成String,String转List,Map转String,String转Map等 集合与字符串相互转换,可以自己扩展源码,带有注释
首先,通过`_bstr_t`构造函数将`std::string`的`c_str()`转换为BSTR类型,然后将BSTR类型强制转换为宽字符指针`wchar_t*`,最后将这个指针转换为`std::wstring`对象。 #### `wstring`到`string` ```cpp string ws2s...
在本实验中,我们将学习如何使用条件转移指令、串操作指令和循环指令来编写一个将一个包含20个元素的数组STRING分成一个偶数数组STRING1和一个奇数数组STRING2的程序。 二、实验要求 1. 掌握条件转移指令的使用...
在计算机科学领域,字符编码是数据处理和存储中不可或缺的一部分,UTF-8和字符串(string)之间的转换是常见的操作。UTF-8是一种广泛使用的Unicode字符编码,它可以表示Unicode字符集中的所有字符,而字符串则通常指的...
Java 中 String 类型转换方法 Java 中 String 类型转换方法是一种常见的编程...Java 中 String 类型转换方法有多种形式,每种形式都有其特点和应用场景,掌握这些方法可以帮助开发者更好地进行数据类型之间的转换。
最近开发遇到blob类型转换为String,一时犯难。所以总结了一段代码与之分享。亲测
这些方法都是通过某种方式将数组中的每个元素连接起来,形成一个新的字符串。需要注意的是,不同的编程语言提供了不同的工具来处理字符串操作,选择哪种方法取决于具体的需求和性能考虑。在处理大量数据时,可能需要...
分享在JAVA中Blob转换成String实例
在这个场景中,"文件转换(inputString)"可能是指将一个字符串(String)形式的数据转换为InputStream对象,或者反过来,将InputStream对象转化为字符串。这通常发生在我们需要在网络上传输数据、存储数据或者在...
一、文件转STRING 1. 文件读取:首先,我们需要读取文件的内容。在Python中,可以使用`open()`函数以二进制模式('rb')打开文件,然后使用`read()`方法获取文件的二进制数据。 ```python with open('filename', '...