`
zyongsheng83
  • 浏览: 43313 次
  • 性别: Icon_minigender_1
  • 来自: 大连
最近访客 更多访客>>
社区版块
存档分类
最新评论

java中的String与常量池

    博客分类:
  • jse
阅读更多

1. 首先String不属于8种基本数据类型,String是一个对象。

因为对象的默认值是null,所以String的默认值也是null;但它又是一种特殊的对象,有其它对象没有的一些特性。

2. new String()和new String(“”)都是申明一个新的空字符串,是空串不是null;

3. String str=”kvill”;

String str=new String (“kvill”);的区别:

  在这里,我们不谈堆,也不谈栈,只先简单引入常量池这个简单的概念。

  常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。

  看例1:

String s0=”kvill”;
String s1=”kvill”;
String s2=”kv” + “ill”;
System.out.println( s0==s1 );
System.out.println( s0==s2 ); 

  结果为:

true
true 

  首先,我们要知道Java会确保一个字符串常量只有一个拷贝。

  因为例子中的s0和s1中的”kvill”都是字符串常量,它们在编译期就被确定了,所以s0==s1为true;而”kv”和”ill”也都是字符串常量,当一个字符串由多个字符串常量连接而成时,它自己肯定也是字符串常量,所以s2也同样在编译期就被解析为一个字符串常量,所以s2也是常量池中”kvill”的一个引用。

  所以我们得出s0==s1==s2;

  用new String() 创建的字符串不是常量,不能在编译期就确定,所以new String() 创建的字符串不放入常量池中,它们有自己的地址空间。

  看例2:

String s0=”kvill”;
String s1=new String(”kvill”);
String s2=”kv” + new String(“ill”);
System.out.println( s0==s1 );
System.out.println( s0==s2 );
System.out.println( s1==s2 ); 

  结果为:

false
false
false 

  例2中s0还是常量池中”kvill”的应用,s1因为无法在编译期确定,所以是运行时创建的新对象”kvill”的引用,s2因为有后半部分new String(“ill”)所以也无法在编译期确定,所以也是一个新创建对象”kvill”的应用;明白了这些也就知道为何得出此结果了。

4. String.intern():

  再补充介绍一点:存在于.class文件中的常量池,在运行期被JVM装载,并且可以扩充。String的intern()方法就是扩充常量池的一个方法;当一个String实例str调用intern()方法时,Java查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其的引用,如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用;看例3就清楚了

  例3:

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 //虽然执行了s1.intern(),但它的返回值没有赋给s1
true //说明s1.intern()返回的是常量池中”kvill”的引用
true 

  最后我再破除一个错误的理解:

  有人说,“使用String.intern()方法则可以将一个String类的保存到一个全局String表中,如果具有相同值的Unicode字符串已经在这个表中,那么该方法返回表中已有字符串的地址,如果在表中没有相同值的字符串,则将自己的地址注册到表中“如果我把他说的这个全局的String表理解为常量池的话,他的最后一句话,“如果在表中没有相同值的字符串,则将自己的地址注册到表中”是错的:

  看例4:

String s1=new String("kvill");
String s2=s1.intern();
System.out.println( s1==s1.intern() );
System.out.println( s1+" "+s2 );
System.out.println( s2==s1.intern() ); 

  结果:

false
kvill kvill
true 

  在这个类中我们没有声名一个”kvill”常量,所以常量池中一开始是没有”kvill”的,当我们调用s1.intern()后就在常量池中新添加了一个”kvill”常量,原来的不在常量池中的”kvill”仍然存在,也就不是“将自己的地址注册到常量池中”了。

  s1==s1.intern()为false说明原来的“kvill”仍然存在;

  s2现在为常量池中“kvill”的地址,所以有s2==s1.intern()为true。

5. 关于equals()和==:

  这个对于String简单来说就是比较两字符串的Unicode序列是否相当,如果相等返回true;而==是比较两字符串的地址是否相同,也就是是否是同一个字符串的引用。

6. 关于String是不可变的

  这一说又要说很多,大家只要知道String的实例一旦生成就不会再改变了,比如说:String str=”kv”+”ill”+” “+”ans”;
就是有4个字符串常量,首先”kv”和”ill”生成了”kvill”存在内存中,然后”kvill”又和” “ 生成 ”kvill “存在内存中,最后又和生成了”kvill ans”;并把这个字符串的地址赋给了str,就是因为String的“不可变”产生了很多临时变量,这也就是为什么建议用StringBuffer的原因了,因为StringBuffer是可改变的

 
分享到:
评论

相关推荐

    Java String 字符串常量池解析

    Java String 字符串常量池解析 Java 中的字符串常量池是一种为了提高性能和减少内存开销的机制。它是 JVM 实例化字符串常量时进行的一些优化,主要是为了减少字符串对象的创建和存储。 字符串常量池的设计思想是...

    【Java面试题】对String常量池的理解

    【Java面试题】对String常量池的理解

    java String源码和String常量池的全面解析

    Java String 源码和 String 常量池是 Java 语言中非常重要的两个概念,它们之间存在着紧密的联系。在 Java 语言中,String 类是不可变的,finalize 方法被禁用,以确保 String 对象的安全性。String 类实现了 ...

    java 内存中 堆、栈、常量池、方法区的总结

    在Java内存管理中,堆(Heap)、栈(Stack)、常量池(Constant Pool)和方法区(Method Area)是四个核心概念,它们在Java程序运行时扮演着不同的角色。 首先,方法区是用来存放类的信息、常量、静态变量等数据的...

    java内存分配之常量池,栈,堆1

    在Java中,内存主要分为四个区域:寄存器、栈、堆和方法区(包括常量池)。以下是这四个区域的详细说明: 1. **寄存器**: 这是计算机硬件的一部分,用于存储非常快速访问的数据。在Java中,寄存器主要由JVM直接管理...

    string常量池和intern_韩雅茹Java系列2021.pdf

    在Java中,有两种创建字符串对象的方式:直接使用双引号声明出来的String对象会直接存储在常量池中。如果不是用双引号声明的String对象,可以使用String提供的intern方法。intern方法会从字符串常量池中查询当前字符...

    Java堆、栈和常量池——内存剖析

    ### Java堆、栈和常量池——内存剖析 #### 寄存器 寄存器作为最快的存储区域之一,由编译器自动管理分配与回收,它位于CPU内,用于存储临时变量,例如局部变量和一些操作数。由于寄存器的数量有限且由编译器自动...

    Java中的String池

    当我们使用`new String("Hello")`创建字符串时,即使字符串字面量已经存在于常量池中,也会创建一个新的String对象。这是因为`new`关键字总是创建一个新的对象实例。 #### 示例代码解析 考虑下面这段示例代码: `...

    Java堆,栈和常量池详解

    在深入探讨Java中的堆、栈以及常量池之前,我们先来简要回顾一下Java内存模型的基本概念。Java程序运行时会使用到不同的内存区域来存储各种类型的数据,这些区域包括:寄存器、虚拟机栈、本地方法栈、Java堆、方法区...

    java String类常量池分析及"equals"和"==”区别详细介绍

    在Java编程语言中,`String`类是一个...总的来说,Java中的`String`类和它的常量池,以及`equals()`和`==`的区别,是理解Java内存管理和对象比较的关键知识点。掌握这些知识,有助于编写出更加高效、健壮的Java代码。

    我们一起学Java之String

    在JDK 8版本中,字符串常量池的位置发生了变化,从方法区移至Java堆中,但这并不影响程序员对字符串常量池的概念理解与使用。理解这一点对编写高效代码十分关键。 当程序需要存储一段字符串时,字符串常量池的机制...

    java常量池分析.pdf

    根据《深入JAVA虚拟机》所述,常量池中的字符串值存储在`CONSTANT_String_info`表中,这个表专门用于存储字符串文字,而不是符号引用。 对于`String s = "haha"`的情况,"haha"的值在内存中的位置是在方法区的常量...

    java中常量以及常量池

    1、举例说明 变量 常量 字面...  静态常量池:*.class文件中的常量池,class文件中的常量池不仅仅包含字符串,数值字面量,还包含类、方法的信息,占用class文件绝大部分空间。  运行时常量池:是jvm虚拟机在完成类装

    深入了解java 中的String

    Java 中存在一个特殊的概念叫做“字符串池”或“字符串常量池”。当直接使用双引号定义字符串时,该字符串会被自动放入字符串池中。例如: ```java String s = "abc"; ``` 如果之后再次尝试创建相同的字符串,Java ...

    什么是字符串常量池?Java开发Java经验技巧共6页.p

    在Java编程语言中,字符串常量池(String Constant Pool)是一个重要的概念,它与程序的内存管理和性能优化密切相关。理解这个概念对于任何Java开发者来说都至关重要。字符串常量池是Java虚拟机(JVM)在运行时为...

    java堆、栈和常量池

    对于String常量,其值是直接存储在常量池中的。虚拟机为每个被加载的类型维护一个常量池,它是该类型所使用的常量的一个有序集合。 - **结构形式**:在JVM中,常量池是以表的形式存在的。对于String类型,有一张...

    解析Java中的String对象的数据类型 字符串

    在Java中,如果我们使用字面值方式创建的String对象,它们是常量池中的字符串常量,如果我们使用new关键字创建的String对象,它们是运行时创建的新对象。例如,String s0="kvill";,String s1=new String("kvill");...

    Java 之 String 类型

    - String对象在Java中是通过引用常量池中的常量来创建的,一旦创建就不能改变。例如,`String str = "Hello"` 创建了一个字符串对象。 - 因为不可变性,每次对字符串进行修改(如使用`concat()`或`substring()`)...

    介绍java中String类的方法

    ` 这种方式会在堆内存中创建一个新的对象,即使字符串内容与常量池中的相同,也会创建新的实例。 2. **String的比较**: - 使用`==`比较的是两个对象的引用,如果指向的是同一个内存地址,返回`true`,否则`false`...

    深入探索Java常量池

    例如,在String类中,intern()方法可以将字符串常量池中的对象返回,而不是创建新的字符串对象。在Integer类中,valueOf方法可以从常量池中获取对象,而不是创建新的Integer对象。 Java常量池是Java虚拟机中一个...

Global site tag (gtag.js) - Google Analytics