本文章分为三个部分:

1、创建字符串对象的两种方式以及它们的存储方式

2、String a = new String("a")创建了几个对象的问题

3、字符串小例子

----------------------------------------------我是友好的分隔线----------------------------------------------

  在《Java核心技术I》中对String类的描述就是“由于不能修改Java字符串中的字符,所以在Java文档中将String类对象称为不可变字符串......编译器可以让字符串共享”。可是在哪里可以实现“共享”这个操作呢?字符串池

  我们知道创建一个字符串对象有两种方式:1) 采用字面值的方式赋值 2) 采用new关键词新建一个字符串对象。

  方式一:采用字面值的方式赋值

  首先我们先举个小例子:

public class StringTest {
public static void main(String[] args) {
String a = "aaa";
String b = "aaa";
}
}

  一般的做法是直接用System.out.println(a==b);来判断,此处用javap -v反编译的方式来判断a和b的值是不是来自同一个地方。

  这里的ldc的含义是:将常量值从常量池中取出来并且压入栈中。

  我们可以看到,a和b是指向同一个字符串对象的,因为"aaa"这个字符串对象在字符串池中,而字符串池是常量池的一种,而且我们可以从"LocalVariableTable"得知,在编译期间,a和b的值就已经确定好了。如果想要创建一个字符串对象,编译器会先在字符串池中查找是否有相同字符串的对象,如果有,就可以直接指向这个对象(多个变量可共享同一个对象),如果没有,那就创建一个新的字符串对象。

  方式二:采用new关键词新建一个字符串对象

  还是先举一个小例子:

public class StringTest {
public static void main(String[] args) {
String a = new String("bbb");
String b = new String("bbb");
}
}

  用javap -v反编译之后得到:

  我们可以看到,这里既有用在字符串池创建的对象的方式(红色),也有调用String类并启用来创建对象(绿色)。其实在使用new关键词创建字符串对象的流程是这个样子的:JVM会先在字符串池中寻找"bbb"这个对象,如果有,就不会在字符串池中创建这个对象,而且直接在堆创建“bbb”这个字符串对象,并将这个对象的地址返回给a;如果没有,则会先在字符串池中创建"bbb"对象,然后再在堆中创建"bbb”这个对象并把这个对象的地址返回给a。因为a和b都是分别new了一个字符串对象,所以它们的字符串对象的地址是不同的。但是我们可以从"LocalVariableTable"中可以看到,a和b变量在字符串池中的对象是在编译期间就已经创建好了,但是因为a和b的字符串对象是用new的方式创建的,所以,a和b的创建需要在运行的时候才能全部完成。

  总而言之,无论是用哪种方式创建字符串对象,都需要在字符串池中进行字符串对象的创建,如果是用new关键词创建对象的话,还需要在堆中创建对象并将对象的地址返回给变量。

----------------------------------------------我是友好的分隔线----------------------------------------------

  有一道面试题是这样子的,“String a = new String("a")”是创建了几个对象?

  其实,这道题可以用我们上面对字符串创建的分析来作答:创建了一个或者两个对象。

  这里给两个提示:1) String a = new String("a"); 2) String a = "a"; String b = new String("a");

  具体要怎么分析可以参考这篇文章https://blog.csdn.net/limingchuan123456789/article/details/14150327,不过只要理解了上面的分析,这道题解答起来并不难。

----------------------------------------------我是友好的分隔线----------------------------------------------

  下面是关于字符串的一些小例子,看看都能做对吗?

public class StringTest {
public static void main(String[] args) {
String a = new String("aaa");
String b = "aaa";
String c = "a"+new String("aa");
String d = "a"+"aa";
System.out.println(a==b);
System.out.println(a==c);
System.out.println(b==c);
System.out.println(b==d);
System.out.println(c==d);
}
}

  答案是:

false
false
false
true
false

  

参考:

https://www.cnblogs.com/fangfuhai/p/5500065.html

https://blog.csdn.net/limingchuan123456789/article/details/14150327

Java中的字符串问题的更多相关文章

  1. [原创]Java中的字符串比较,按照使用习惯进行比较

    java中的字符串比较一般可以采用compareTo函数,如果a.compareTo(b)返回的是小于0的数,那么说明a的unicode编码值小于b的unicode编码值. 但是很多情况下,我们开发一 ...

  2. 理解Java中的字符串类型

    1.Java内置对字符串的支持: 所谓的内置支持,即不用像C语言通过char指针实现字符串类型,并且Java的字符串编码是符合Unicode编码标准,这也意味着不用像C++那样通过使用string和w ...

  3. Java中的字符串驻留

    转自:http://www.cdtarena.com/javapx/201307/9088.html 最近在工作的时候,一句再正常不过的代码String a = “hello” + “world”;被 ...

  4. Java中的字符串拼接

    Java中的字符串拼接 1.设计源码 /** * @Title:IndexOf.java * @Package:com.you.freemarker.model * @Description: * @ ...

  5. java中,字符串类型的时间数据怎样转换成date类型。

    将字符串类型的时间转换成date类型可以使用SimpleDateFormat来转换,具体方法如下:1.定义一个字符串类型的时间:2.创建一个SimpleDateFormat对象并设置格式:3.最后使用 ...

  6. Android学习笔记----Java中的字符串比较

    用习惯了C#.C++,在做字符串比较时想当然地使用如下语句: string str1 = "abcd", str2 = "abcd"; if(str1==str ...

  7. 转载:Java中的字符串常量池详细介绍

    引用自:http://blog.csdn.net/langhong8/article/details/50938041 这篇文章主要介绍了Java中的字符串常量池详细介绍,JVM为了减少字符串对象的重 ...

  8. 《Java入门第三季》第二章 认识 Java 中的字符串

    什么是 Java 中的字符串.1.在Java的世界里,字符串被作为String类型的对象处理. 2.通用的初始化的方式:String s = new String("i love you & ...

  9. 为什么Java中的字符串是不可变的?

    原文链接:https://www.programcreek.com/2013/04/why-string-is-immutable-in-java/ java字符串是不可变的.不可变类只是一个不能修改 ...

  10. 详解Java中的字符串

    字符串常量池详解 在深入学习字符串类之前, 我们先搞懂JVM是怎样处理新生字符串的. 当你知道字符串的初始化细节后, 再去写String s = "hello"或String s ...

随机推荐

  1. 安装MySQL出现1045错误,卸载不干净

    安装MySQL出现1045错误 一.运行环境 MySQL mysql-5.1.26-rc-win32 操作系统:Windows 7 X64 二.问题描述 安装MySQL过程中会涉及对root密码的设置 ...

  2. 常用转义字符例如&的含义

    &amp中的amp就是英文ampersand的缩写,该词的意思是&这个符号& 是 HTML 中 & 的表示方法.即在html中用&表示&符号

  3. OC官方文档翻译-Working-with-Protocols-协议的使用

    查看全部文档翻译,请浏览https://github.com/L1l1thLY/Programming-with-Objective-C-in-Chinese,blog仅收录本人翻译的两章. 简述 在 ...

  4. SCUT - 289 - 小O的数字 - 数位dp

    https://scut.online/p/289 一个水到飞起的模板数位dp. #include<bits/stdc++.h> using namespace std; typedef ...

  5. 读《JavaScript权威指南》笔记(二)

    1.加号运算和比较运算符的区别 对于数字和字符串操作符来说,加号运算符和比较运算符的行为都有所不同,前者更偏爱字符串,如果它的其中一个操作数是字符串的话,则进行字符串连接操作.而比较运算符则更偏爱数字 ...

  6. 解读人:刘佳维,Spectral Clustering Improves Label-Free Quantification of Low-Abundant Proteins(谱图聚类改善了低丰度蛋白的无标记定量)

    发表时间:(2019年4月) IF:3.95 单位: 维也纳医科大学: 欧洲生物信息研究所(EMBL-EBI): 分子病理学研究所: 奥地利科学院分子生物技术研究所: Gregor Mendel分子植 ...

  7. Unity---UNet学习(2)----简单mmo游戏实现

    1.实现步骤 新建空物体Controller,添加Network Manager.HUD组件. 创建Player模型,添加Inentity组件. Player添加脚本控制移动,只有当为本地用户才执行. ...

  8. Miller-Rabin素性测试|Pollard's Rho算法

    Miller-Rabin 素性测试 Miller-Rabin 素数测试 一本通上的M-R不透彻啊~ Miller-Rabin是利用随机化算法判断一个数是合数还是素数. 首先,如果一个数N是素数,那么他 ...

  9. 继承、super、this、抽象类

    继承.super.this.抽象类 继承.super.this.抽象类 继承.super.this.抽象类 继承.super.this.抽象类 继承.super.this.抽象类

  10. EIGRP-5-EIGRP数据包格式

    EIGRP数据包直接承戟在IP数据包中.协议号为88.EIGRP数据包的最大长度取决于具体接口上的最大IP MTU设置——通常完整IP数据包为1500字节.其中1480字节可以用于 EIGRP数据包. ...