`
JackyCheng2007
  • 浏览: 253318 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java String 详解 - String Literal

阅读更多
为了性能和内存资源上的考虑,JVM对String类型的数据做了特殊的处理。也就是大家都知道的String是immutable的或者是constant。其实很多面试或者笔试里面都会考到。有时觉得没事找事,确实,对于一般的系统,不需要考虑到底创建了几个string,只管用就是,似乎JVM会处理,至少会GC他们的。其实不然。对于大型项目,或者运行很长时间的项目,或者使用到大量字符串的项目来说,String的开销就不得不考虑。
1. String Literal Constant Pool
引用
By literal we mean any number, text, or other information that represents a value. This means what you type is what you get.

literal,就是字符串,数字等值本身。当你在编码的时候写下一个值的时候,比如10,或者“abc”你就写了一个literal。
JVM 维护了一个String Literal Pool,用来存储String Literal。
引用
A string literal consists of zero or more characters enclosed in double quotes.
A string literal is a reference to an instance of class String. Moreover, a string literal always refers to the same instance of class String.

字符串字是一个由双引号括起来的字符序列。它是指向一个String实例的引用。
比如 String s = “abc”。对于“abc”,它首先是一个String literal,它在创建之后,立即利用String的intern方法,装入到了Literal Pool并返回这个String 实例的引用给s。当你再次写abc”的时候,intern方法会先查看是否已有这个literal了,就会直接返回这个literal对应的String实例的引用。也就是说你循环1000变,内存里面也只有这么一个String literal以及他对应的String的实例。String,本质上是一个Java 类,它的实例除了包含value,也就是这个字符序列外,还有其他的属性和方法。这样看来String Object和Literal本质上是不同的。
其实除了String Literal,还有其他类型的Literal:
引用

  • IntegerLiteral
  • FloatingPointLiteral
  • BooleanLiteral
  • CharacterLiteral
  • StringLiteral
  • NullLiteral


只是,只有String Literal有这么一个pool,用来提高性能和节约内存。提高性能,是因为你可以重用已经有的String Object,这样也就节约了内存。
再来看看 new String("abc"), 只有用了双引号,就会涉及到string literal,它的逻辑就是先查看是否已有这个literal,有就返回它的string object 引用,没有就创建一个,并生成一个string的object,然后把这个object的引用返回。可见,没有string literal有且仅有一个string object与之对应。回到这句话,new String("abc"),只有用到new,就会新建一个object,这里是新建一个string object。这就都明白了吧。看一个例子:

package jdk.lang;
public class StringTest {
	public static void main(String[] args) {
		String s1 = "abc";
		String s2 = "abc";
                System.out.println(s1 == s2);
        }
}

输出 true。也就是只生成了一个对象。
2. 编译时计算和运行时计算的区别
看下面:
package jdk.lang;
public class StringTest {
	public static void main(String[] args) {
		String s1 = "abc";
		String s2 = "abc";
		String s3 = s1 + s2;
		String s4 = "abc" + "abc";
		String s5 = "ab" + "cabc";
		System.out.println(s3 == s4);
		System.out.println(s4 == s5);
        }
}

输出:false true。上面的程序,"abc" + "abc"是常量运算表达式constant expression。编译器就可以计算出值了,这就是编译时计算。同时这个表达式会被看做是string literal。但是:String s3 = s1+s2;那么s3的值就只能在运行的时候才能确定,这就是运行时计算。可见运行时会创建一个新的String,并且不会被当成string literal。
3. Intern
下面是String的intern方法的注释和签名,可见是一个native方法。
引用

A pool of strings, initially empty, is maintained privately by the class String.
When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.
All literal strings and string-valued constant expressions are interned.
public native String intern();

String提供了方法Intern让我们把显示的调用来把String对象放入到literal pool里面并返回这个新的引用。
package jdk.lang;
public class StringTest {
	public static void main(String[] args) {
		String s1 = "abc";
		String s2 = "abc";
		String s3 = s1 + s2;
		String s4 = s3.intern();
		String s5 = "ab" + "cabc";
		System.out.println(s4 == s5);
		System.out.println(s3 == s5);
                System.out.println(s3.intern() == s3);
		System.out.println(s3.intern() == s4);
		System.out.println(s5.intern() == s5);
        }
}

输出: true false false true true。s4是一个新的引用,这个引用和s5一样,但是和s3不同。也就是说,intern的时候创建了一个新的对象。但是不是每次都新建一个,只要有了,就会返回存在的。最后两个结果就说明了这点。
4. 垃圾回收
GC是不会收集Literal Pool的。但是会收集没有intern的String 变量对象。对上面的例子,s3会被回收,s4就不会。
5. constant expression - 常量表达式
引用
Compile-time constant expressions of type String are always "interned" so as to share unique instances, using the method String.intern.

常量表达式,比如 "ab" + "cabc"会被当成literal,也就等同"abcabc"。


6. 关于其他的Literal呢?

引用

If the value p being boxed is true, false, a byte, or a char in the range \u0000
to \u007f, or an int or short number between -128 and 127 (inclusive), then let
r1 and r2 be the results of any two boxing conversions of p. It is always the case
that r1 == r2.


也就是说,他们是部分重用的。看一个例子:
private static void IntegerLiteral() {
		Integer i1 = 6;
		Integer i2 = 6;
		Integer i3 = 3 + 3;
		Integer i4 = 3 * 2;
		System.out.println(i1 == i2);//true
		System.out.println(i3 == i2);//true
		System.out.println(i4 == i2);//true

		Integer i5 = 128;
		Integer i6 = 128;
		System.out.println(i5 == i6);//false
	}
private static void BoolearnLiteral() {
		Boolean b1 = true;
		Boolean b2 = true;
		System.out.println(b1 == b2);//false
	}






分享到:
评论
1 楼 牛不牛我来 2012-12-18  
哥,这几段英文是出处是哪里啊?请告之下,万分感谢

相关推荐

    String详解

    使用这种方式创建的字符串会被存储在一个特殊的内存区域——字符串常量池(String Literal Pool)中。如果再次尝试创建相同的字符串字面量,Java会直接引用已存在的字符串对象,而不是创建新的实例。 2. **new...

    关于java String中intern的深入讲解

    由于 `stringObject` 已经被添加到字符串常量池中,所以 `stringObject == stringLiteral` 将返回 false。 intern 方法的优点 intern 方法有以下几个优点: * 减少内存的占用:intern 方法可以将字符串对象存储在...

    javascript string tutorial

    stringLiteral = stringLiteral.concat('!!!'); stringObject = stringObject.concat('###'); console.log(stringLiteral); // 输出:This is a string literal!!! console.log(stringObject); // 输出:This is a ...

    XSL速查手册中文版

    ### XSL速查手册知识点详解 #### 一、XSL与XPath基础概念 - **XSL**(Extensible Stylesheet Language)是一种用于转换XML文档的标记语言,它提供了丰富的指令集来实现对XML数据的查询、筛选、排序等功能。 - **...

    java 语言文法

    - `StringLiteral` - `BooleanLiteral` - `NullLiteral` ##### Expression(表达式) - **定义**:表达式是Java中计算结果的基本单位,可以包含变量、运算符和方法调用等。 - **形式**: - `Expression1...

    c字符串,string对象,字符串字面值的区别详解

    字符串字面值(String Literal)是一串由双引号括起的字符常量,例如:"Hello World!"。在C++中,所有字符串字面值在编译时都会在末尾自动添加一个空字符'\0',表示字符串的结束。字符串字面值是不可变的,存储在...

    java_调用Webservice接口

    ### Java调用Webservice接口详解 #### 一、前言 随着互联网技术的发展与进步,Webservice作为一种重要的网络服务标准,被广泛应用于不同系统之间的数据交互。Webservice结合XML技术,能够实现跨平台、跨语言的数据...

    用axis1.4发布自己的wsdl服务详解

    <service name="HelloWorldWSDD" provider="java:RPC" style="wrapped" use="literal"> <!-- 指定类名 --> *"/> <!-- 允许所有方法 --> <!-- 设置作用域 --> ``` 4. **重启Tomcat服务** 执行`...

    java中的Class类和反射.docx

    ### Java中的Class类和反射详解 #### 一、Class类的作用与意义 在Java中,`Class`类是一个非常核心且强大的类,它提供了一系列的方法来获取类的信息以及操作类。`Class`类实例通常代表了一个正在运行的Java应用...

    WebService入门案例java工程代码

    **WebService入门案例java工程代码详解** 在IT行业中,WebService是一种基于开放标准的、平台无关的交互方式,允许不同系统之间交换数据。它通过SOAP(Simple Object Access Protocol)协议传输数据,使用WSDL(Web...

    xfire框架构建webservice应用(myecllipse自动代码生成 )

    2. **灵活性**:支持多种绑定方式,包括RPC/encoded、RPC/literal和Document/literal。 3. **性能**:XFire通过优化XML解析和序列化过程来提高性能。 4. **易于集成**:可以很容易地与Spring框架集成。 #### 二、...

    java 基础学习

    ### Java基础学习知识点详解 #### 一、基本编程要素 在Java编程中,掌握基本的编程要素至关重要。这些要素构成了程序的基础,对于理解和编写代码都非常重要。 - **数据类型(Datatypes)**:数据类型定义了变量...

    java调用webservice的各种方法总结

    ### Java调用WebService的各种方法详解 #### 一、利用JDK Web Service API实现 通过Java标准库中的WebService API,可以直接创建并发布一个简单的WebService。这种方式适用于那些希望避免引入额外依赖的场景。 ##...

    webservice

    public String say(String name) { return ("Hello: " + name); } } ``` - `@WebService` 注解指示 JAXWS 此类是一个 Web 服务。 - `@WebMethod` 注解用于标记公共方法,使其成为 Web 服务的操作。 #### 六、...

    Python中函数eval和ast.literal_eval的区别详解

    string <==> list string <==> tuple string <==> dict 也就是说,使用eval可以实现从元祖,列表,字典型的字符串到元祖,列表,字典的转换,此外,eval还可以对字符 串型的输入直接计算。比如,她会将...

    导出Excel的示例

    - 定义了三种样式:`Default`、`BoldColumn` 和 `StringLiteral`。 - `Default`:默认样式,用于普通单元格。 - `BoldColumn`:粗体边框样式,通常用于列标题。 - `StringLiteral`:文本样式,用于存储字符串...

    Java反射如何有效的修改final属性值详解

    2. Literal String类型(直接用双引号定义的字符串)。 对于不会被内联优化的`final`属性,我们可以通过反射有效地进行修改。例如,将`name`属性的定义改为`new String("Mike")`: ```java public final String ...

Global site tag (gtag.js) - Google Analytics