以前关于String的理解仅限于三点:
1、String 是final类,不可继承
2、String 类比较字符串相等时时不能用“ == ”,只能用  "equals" 
3、String  类不可更改

String 使用非常方便,因此一般涉及字符串时都用该类进行字符串处理
至于String类的类在机制,则极少去探究。

直到读到下面这个例子。

class X
{  
   public static String strX="hello";
}
class Y
{
   public static String strY="hello";
}
class Z
{
   public static String strZ="hell"+"o";
}
class Test
{
   public static void main(String[] args)
   {
        System.out.println( X.strX==Y.strY);  
        System.out.println( X.strX==Z.strZ);
        String s1="hel";
        String s2="lo";
        System.out.println( X.strX==(s1+s2));
        System.out.println( X.strX==(s1+s2).intern());
    }
}

按照我的理解,类X,类Y,类Z中的三个常量字符串属于不同的对象,用 == 操作符比较,那么结果必然是 false,输出应该为:
false
false
false
false

但实际上输出确是:
true
true
false
true
使我大惑不解。并因此找了许多资料来看(尤其是C++和Java比较编程,里面解释比较详细),终于逐渐明白了原因。

== 只有在两个比较对象指向同一对象时,其值才为true。X.strX==Y.strY 与 X.strX==Z.strZ 测试结果都为true,说明这三个常量指向的都是同一个对象。
在JAVA中,String 是字符串常量。由相同序列的字符组成的两个字符串属于同一对象,位于内存中的同一个位置。每个字符串常量只有一个 String 对象来表示。即使这个字符串常量出现在一个程序的不同位置甚至一个程序的不同程序包中。也就是说,X.strX 与 Y.strY 由于都是同一字符序列,因此 指向的肯定是同一对象。
Z.strZ 也是如此。"hell"+"o",两个常量字符串相加后,创建了一个新的字符串常量(这个工作是编译期间完成的),它与 X.strX ,Y.strY有相同的字符序列,因此指向同一对象 。

虽然一个常量表达式将两个字符串常量链接在一起的结果在编译器已完成,但是 
 String s1="hel";
 String s2="lo";
 String s3=s1+s2;
这段代码中,s3只能在运行期间创建。这三条语句所创建的"hello"字符串作为String对象存储在内存中的一个独立位置。

Java提供一个机制,通过String类定义的intern()方法把一个运行时创建的字符串加到字符串常量池(如果它还没有入池)。如果上面的三条代码改为:
 String s1="hel";
 String s2="lo";
 String s3=(s1+s2).intern();
java将把 s1+s2 所返回的字符串对象中的字符序列与已经存储在字符串常量池中的字符串进行比较。如果找到一个匹配,intern()就返回这个字符串的引用。如果没有找到匹配,s1+s2 所返回的字符串将被加入到字符串常量池中,并返回这个字符串常量的引用。
这就解释了为社么X.strX==(s1+s2)返回false,而X.strX==(s1+s2).intern()返回true。(s1+s2).intern()指向strX,strY,StrX指向的字符串常量"hello"。

本人追加测试代码如下:

/**
*
* @author ocq
*/
public class testString{

public static void main(String[] args) {

String s1 = "a";
String s2 = "b";
String s3 = "ab";
String s4 = s1 + s2;
String s5 = "a" + "b";
String s6 = s1 + "b";
StringBuffer s7 = new StringBuffer("abc");
String s8 = s7.substring(3);
StringBuffer s9 = new StringBuffer("abc");

System.out.println((s3 == s4));//false
System.out.println(s3 == s5);//true
System.out.println(s3 == s6);//false
System.out.println(s4 == s6);//false
System.out.println((s4 == s8));//false
System.out.println((s7.toString() == s9.toString()));//false

}
}

原文:http://blog.csdn.net/kofsky/article/details/1882626

Java常量字符串String理解 String理解的更多相关文章

  1. Java常量字符串String理解

    Java常量字符串String理解 以前关于String的理解仅限于三点:1.String 是final类,不可继承2.String 类比较字符串相等时时不能用“ == ”,只能用  "eq ...

  2. java常量,变量,静态变量的理解

    最近考试出了一个很简单的题,看看他们对java常量,变量,静态变量的理解,代码如下: public class TestVar { /** * JAVA基础,常量,变量,静态变量 */ public ...

  3. Java基础-字符串连接运算符String link operator

    Java基础-字符串连接运算符String link operator 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 字符串链接运算符是通过“+”进行拼接的. 一.使用“+”进行字 ...

  4. IntelliJ IDEA Error:(24, 35) java: 常量字符串过长

    在转换一个JSON转Java对象是 idea 编译不通过  提示:Error:(24, 35) java: 常量字符串过长 File -> Settings -> Build,Execut ...

  5. IDEA报错 Error:(24, 35) java: 常量字符串过长

    修改设置

  6. Java常量定义需要注意的两点

    在任何开发语言中,都需要定义常量.在Java开发语言平台中也不例外.不过在Java常量定义的时候,跟其他语言有所不同.其有自己的特色.在这篇文章中,主要针对Java语言中定义常量的注意事项进行解析,帮 ...

  7. Java 之字符串(7)

    什么是 Java 中的字符串 在程序开发中字符串无处不在,如用户登陆时输入的用户名.密码等使用的就是字符串.其实,在前面的章节中我们就已经使用了字符串, 例如我们在控制台中输出的 "Hell ...

  8. Java的字符串操作

    目录 Java的字符串操作 一.不同字符串操作的对比 1.1 C++中const修饰指针 const在星号的左边,是被指向的常量不可变 const在星号的右边,是指针的指向不可变 二. Java字符串 ...

  9. 从Java的字符串池、常量池理解String的intern()

    前言 逛知乎遇到一个刚学Java就会接触的字符串比较问题: 通常,根据"==比较的是地址,equals比较的是值"介个定理就能得到结果.但是String有些特殊,通过new Str ...

随机推荐

  1. inux命令英文缩写的含义(方便记忆) 2

    linux常用命令的英文单词缩写 命令缩写: ls:list(列出目录内容) cd:Change Directory(改变目录) su:switch user 切换用户rpm:redhat packa ...

  2. systemd基础

    systemd 起源 systemd这一名字源于Unix中的一个惯例:在Unix中常以“d”作为系统守护进程(英语:daemon,亦称后台进程)的后缀标识.除此以外,systemd亦是借代英文术语D体 ...

  3. fastdfs5.10 centos6.9 安装配置

    下载相关软件 https://codeload.github.com/happyfish100/fastdfs/tar.gz/V5.10http://download.csdn.net/detail/ ...

  4. hdu4796

    4月真是没写啥题,这题还是月初写的…… 不错的插头dp,首先由n和m的范围知肯定是轮廓线是横向划的 问题的难点在于怎么处理下面两个问题 1.怎么处理独立插头 2.怎么处理完全将W和L左右隔开 先说独立 ...

  5. c++ primer 11 泛型算法

    使用泛型算法必须包含头文件#inlucde <algorithm> 标准库还定义一组泛化的算术算法,其命名习惯与泛型算法相同,包含头文件#include <numeric> f ...

  6. 定期删除30天以前的elasticsearch的日志

    脚本/scripts/delete-elk.log #!/bin/bash DATE=`date -d "1 days ago" +%Y.%m.%d` ip=`ifconfig e ...

  7. css特效-一道闪光在图片上划过

    在百度音乐 http://music.baidu.com/ 看到这么一个图片效果,当鼠标移上去的时候,会有一道闪光在图片上划过,效果挺酷炫的.于是把这个效果再实现一下:大体思想是,设计一个透明层i,s ...

  8. 洛谷P1528 切蛋糕 [搜索,二分答案]

    题目传送门 切蛋糕 题目描述 Facer今天买了n块蛋糕,不料被信息组中球球等好吃懒做的家伙发现了,没办法,只好浪费一点来填他们的嘴巴.他答应给每个人留一口,然后量了量每个人口的大小.Facer有把刀 ...

  9. Android之 广播

    (以下内容是阅读郭霖大神的<第一行代码>后自己总结的) 1.概述 广播是Android的四大组件之一. Android的广播机制十分灵活. 2.发送广播 如上图Android的广播主要分为 ...

  10. Python 正则表达式中级

    首先是?:   在括号中用?:用在findall和split之中,去除括号优先级. 如果不用只输出括号内匹配的值 r   的作用是转义python里面换行符等,像是\n 不用加\来转义 1.子表达式 ...