Java中String类由于其特殊性(不变类),几乎是笔试面试中的必考题,当然有些题目其实没啥意思,不过关键是要通过题目掌握原理性的东西。下面六道题目,如果您全部做对了,且明白其所以然,那么Java中的关于String的笔试面试题应该难不到你了。也许您觉得polaris说的有点过了,然而彻底明白这些题目,对理解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)通过java源码分析String
我们都知道String是不可变的(immutable),不变性的体现是:String类内部通过char数组来保存字符串,而这个char数组被声明为:final。那么为什么要将String类声明为不可变呢?了解设计模式的你应该知道有一种模式叫做“不变模式”(immutable pattern),String类的设计就是使用了不变模式,有兴趣的朋友可以看看“不变模式”讲的具体是啥东东。
说完String的不可变性,需要说说String的“final性”(其实也还是不可变性决定的)。这也是有些面试官会问到的问题:我能不能写一个类继承自String?为什么?我们来看看String类的声明:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence
对于final关键字的作用不用多解释了。其实这也是“强不变模式”的一种要求(类本身声明为final或所有方法声明为final)。
(2)理解String对象的存储机制
要深入理解String必须先了解Java内存机制——运行时数据区(Runtime Data Area)。《The JavaTM Virtual Machine Specification》中将运行时数据区分为六部分(参看第三章):
1)The pc Register;2)Java Virtual Machine Stacks;3)Heap;4)Method Area;5)Runtime Constant Pool;6)Native Method Stacks;
以上数据区的具体描述可参考规范。需要注意的是,以上只是一个规范说明,并没有规定虚拟机如何实现这些数据区。
在说明String对象存储机制之前,我们需要先了解数据区的三个部分:Java 虚拟机栈(可以简称为Java栈)、堆和运行时常量池(简称常量池)。对于Java栈和堆大家应该比较熟悉,这里有一个关键点是常量池,下面就重点介绍一下与String相关的常量池。
首先大概描述一下什么是常量池:
虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用常量的一个有序集合,包括直接常量(string,integer和floating point常量)和对其他类型、字段和方法的符号引用。池中的数据项就像数组一样是通过索引访问的。因为常量池存储了相应类型所用到的所有类型、字段和方法的符号引用,所以它在Java程序的动态链接中起着核心的作用。
<1> String相关常量池
在《The JavaTM Virtual Machine Specification》第四章有一节是专门讲解各种常量池的,其中有两个常量池是关于String的。
1)The CONSTANT_String_info Structure
对于常量池的细节此文不做过多介绍,polaris以后可能会写一序列关于Java虚拟机的文章。现在您可以查阅规范或在网上收集相关资料阅读。规范上对该常量池结构的介绍是:
The CONSTANT_String_info structure is used to represent constant objects of the type String.
在该常量池结构中引用了另一个常量池结构,如2)
2)The CONSTANT_Utf8_info Structure
规范上的描述是:The CONSTANT_Utf8_info structure is used to represent constant string values.
根据上面的介绍可以看出,字符串字面值会存储在常量池中。下面来分析String对象的存储机制。
<2> String对象的存储
请看这样两个语句:
String x = "abc"; String y = new String("abcd");
现在来分析一下内存的分配情况。如图:
可以看出,x与y存在栈中,它们保存了相应对象的引用。第一条语句没有在堆中分配内存,而是将“abc”保存在常量池中。对于第二条语句,同样会在常量池中有一个“abcd”的字符串,当new时,会拷贝一份该字符串存放到堆中,于是y指向了堆中的那个“abcd”字符串。不知道polaris有没有讲明白。如果您明白了,那么做前面那六道题就没什么问题了。
3、六道题答案详解
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
第五题看明白后,第六题就没什么好讲的了。
相关推荐
C语言头文件 STRING.HC语言头文件 STRING.HC语言头文件 STRING.HC语言头文件 STRING.HC语言头文件 STRING.HC语言头文件 STRING.HC语言头文件 STRING.HC语言头文件 STRING.HC语言头文件 STRING.HC语言头文件 STRING....
Map<String, String> map = gson.fromJson(jsonString, new TypeToken<Map<String, String>>(){}.getType()); ``` 4. **String to Object** 如果JSON字符串代表的是一个自定义Java对象,你可以创建一个对应的类...
C#中char[]与string之间的转换 C#中char[]与string之间的转换是一种常见的操作,我们经常需要在这两种数据类型之间进行转换。今天,我们将探讨C#中char[]与string之间的转换,包括string转换成Char[]和Char[]转换成...
### C# String 的各种转换 在C#编程语言中,字符串与数字之间的转换是非常常见的操作。本文将详细介绍如何在C#中实现字符串与其他数据类型(如整数、浮点数等)之间的转换,并特别关注字符串与十六进制之间的转换。...
Java String 类型 API 测试代码 1.String和char[]之间的转换 toCharArray(); 2.String和byte[]之间的转换 getBytes() Arrays工具类 : Arrays.toString(names) String类 String replace(char oldChar, ...
标题与描述中提到的知识点是关于C#编程语言中`String`与`string`的区别,以及`string`类型的深入解析。以下是对这些知识点的详细解释: ### `String`与`string`的区别 #### 1. **位置与来源** - `String`是.NET ...
在Java编程语言中,`String`对象的创建是开发者经常遇到的问题,因为它涉及到内存管理和效率。`String`类在Java中被广泛使用,因为它代表不可变的字符序列,这使得它在很多场景下非常安全。这里我们将深入探讨`...
string 和 char* 的区别和联系 在 C++ 编程中,字符串是一种常用的数据类型,string、CString 和 char*都是字符串的 представители,每种类型都有其特点和使用场景。下面我们将详细介绍 string、...
在Java开发中,JavaBean和JsonString是两种常见的数据表示形式。JavaBean是Java对象的一种规范,用于封装数据,而JsonString是一种轻量级的数据交换格式,常用于前后端交互。本篇将深入探讨JavaBean与JsonString之间...
### List转换成String数组 在Java编程中,我们经常需要对集合进行操作,尤其是在处理大量字符串数据时。本文将详细介绍如何将一个`List<String>`类型的集合转换为`String[]`数组,并通过不同的方法来实现这一过程。...
### String[] 与 List 相互转化 在 Java 编程语言中,`String[]` 数组和 `List` 集合之间的相互转换是非常常见的需求。这两种数据结构各有优势:数组提供了固定长度且访问效率高的特性,而列表则支持动态调整大小...
本文将详细讨论如何在C++中将`double`类型的数值转换为`std::string`字符串,以及如何将`std::string`转换回`double`。我们将基于提供的`stringtodouble`工程文件进行讨论。 首先,让我们探讨`double`转`string`的...
在C++编程中,STL(Standard Template Library)的string类是用于处理文本字符串的强大工具。然而,在处理二进制数据时,需要注意string类的一些特性,因为它通常与文本字符串关联,而二进制数据可能包含特殊的字符...
根据提供的信息,我们可以总结出这份Java基础String类选择题练习题主要聚焦于String及StringBuffer类的使用。尽管具体的题目内容未给出,但从所展示的信息中可以推断出该练习题集涵盖了以下几方面的知识点: ### 一...
### List转换成String数组 在Java编程语言中,经常需要将`List<String>`类型的数据转换为`String[]`数组类型,以便于进行某些特定的操作或适应某些方法的要求。本文将详细探讨这一转换过程,并通过几个具体的示例来...
public static String[] split(String s, String regex) s参数为待拆分字符串, regex参数有两种格式: 单字符的字符串(长度1),功能如下:split(“ab#12#453”, “#”) 返回带5个元素的数组:ab, #, 12, #, 453 ...
"String型的不可变性" Java 中的 String 型是一个特殊的包装类数据,它具有不可变性。什么是不可变性呢?简单来说,就是 String 对象一旦被创建,不能被修改。那么,为什么 String 对象不能被修改呢?这就需要从 ...
在编程领域,尤其是在使用C++、Java或C#等面向对象的语言时,经常需要将字符串数组转换为单一的string类型。这种操作在处理数据输入、输出或者格式化时非常常见。下面我们将详细讨论如何在不同语言中实现这个过程,...
与此相关的,`String`对象是Java编程语言中的基础类型,用于存储和处理文本数据。在实际开发中,我们经常需要在`String`对象与JSON对象之间进行转换,以满足不同的需求。本文将深入探讨`String`与JSON的互转方法,并...
`HexString`和`Base64String`是两种常见的二进制数据的文本表示形式。理解它们的特性和转换方法对于开发人员来说是非常基础且实用的知识。 首先,`HexString`(十六进制字符串)是一种将二进制数据表示为十六进制...