- 浏览: 7978763 次
- 性别:
- 来自: 广州
-
文章分类
- 全部博客 (2425)
- 软件工程 (75)
- JAVA相关 (662)
- ajax/web相关 (351)
- 数据库相关/oracle (218)
- PHP (147)
- UNIX/LINUX/FREEBSD/solaris (118)
- 音乐探讨 (1)
- 闲话 (11)
- 网络安全等 (21)
- .NET (153)
- ROR和GOG (10)
- [网站分类]4.其他技术区 (181)
- 算法等 (7)
- [随笔分类]SOA (8)
- 收藏区 (71)
- 金融证券 (4)
- [网站分类]5.企业信息化 (3)
- c&c++学习 (1)
- 读书区 (11)
- 其它 (10)
- 收藏夹 (1)
- 设计模式 (1)
- FLEX (14)
- Android (98)
- 软件工程心理学系列 (4)
- HTML5 (6)
- C/C++ (0)
- 数据结构 (0)
- 书评 (3)
- python (17)
- NOSQL (10)
- MYSQL (85)
- java之各类测试 (18)
- nodejs (1)
- JAVA (1)
- neo4j (3)
- VUE (4)
- docker相关 (1)
最新评论
-
xiaobadi:
jacky~~~~~~~~~
推荐两个不错的mybatis GUI生成工具 -
masuweng:
(转)JAVA获得机器码的实现 -
albert0707:
有些扩展名为null
java 7中可以判断文件的contenttype了 -
albert0707:
非常感谢!!!!!!!!!
java 7中可以判断文件的contenttype了 -
zhangle:
https://zhuban.me竹板共享 - 高效便捷的文档 ...
一个不错的网络白板工具
链接:http://www.importnew.com/10756.html
在理解字符串常量前,我们先熟悉一下如何创建一个字符串,在Java中有两种方法可以创建一个字符串对象:
使用new运算符。例如:
String str = new String("Hello");
使用字符串常量或者常量表达式。例如:
String str="Hello"; //(字符串常量) 或者
String str="Hel" + "lo"; //(字符串常量表达式).
这些字符串的创建方式之间有什么区别呢?在Java中,equals方法被认为是对象的值进行深层次的比较,而操作符==是进行的浅层次的比较。equals方法比较两个对象的内容而不是引用。==两侧是引用类型(例如对象)时,如果引用是相同的-即指向同一个对象-则执行结果为真。如果是值类型(例如原生类型),如果值相同,则执行结果为真。equals方法在两个对象具有相同内容时返回真-但是,java.lang.Object类中的equals方法返回真-如果类没有覆盖默认的equals方法,如果两个引用指向同一个对象。
让我们通过下面的例子来看看这两种字符串的创建方式之间有什么区别吧。
public class DemoStringCreation {
public static void main(String args[]) {
String str1 = "Hello";
String str2 = "Hello";
System.out.println("str1 and str2 are created by using string literal.");
System.out.println(" str1 == str2 is " + (str1 == str2));
System.out.println(" str1.equals(str2) is " + str1.equals(str2));
String str3 = new String("Hello");
String str4 = new String("Hello");
System.out.println("str3 and str4 are created by using new operator.");
System.out.println(" str3 == str4 is " + (str3 == str4));
System.out.println(" str3.equals(str4) is " + str3.equals(str4));
String str5 = "Hel" + "lo";
String str6 = "He" + "llo";
System.out.println("str5 and str6 are created by using string constant expression.");
System.out.println(" str5 == str6 is " + (str5 == str6));
System.out.println(" str5.equals(str6) is " + str5.equals(str6));
String s = "lo";
String str7 = "Hel" + s;
String str8 = "He" + "llo";
System.out.println("str7 is computed at runtime.");
System.out.println("str8 is created by using string constant expression.");
System.out.println(" str7 == str8 is " + (str7 == str8));
System.out.println(" str7.equals(str8) is " + str7.equals(str8));
}
}
输出结果为:
str1 and str2 are created by using string literal.
str1 == str2 is true
str1.equals(str2) is true
str3 and str4 are created by using new operator.
str3 == str4 is false
str3.equals(str4) is true
str5 and str6 are created by using string constant expression.
str5 == str6 is true
str5.equals(str6) is true
str7 is computed at runtime.
str8 is created by using string constant expression.
str7 == str8 is false
str7.equals(str8) is true
使用相同的字符序列而不是使用new关键字创建的两个字符串会创建指向Java字符串常量池中的同一个字符串的指针。字符串常量池是Java节约资源的一种方式。
字符串常量池
字符串的分配,和其他的对象分配一样,耗费高昂的时间与空间代价。JVM为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化。为了减少在JVM中创建的字符串的数量,字符串类维护了一个字符串池,每当代码创建字符串常量时,JVM会首先检查字符串常量池。如果字符串已经存在池中,就返回池中的实例引用。如果字符串不在池中,就会实例化一个字符串并放到池中。Java能够进行这样的优化是因为字符串是不可变的,可以不用担心数据冲突进行共享。例如:
public class Program
{
public static void main(String[] args)
{
String str1 = "Hello";
String str2 = "Hello";
System.out.print(str1 == str2);
}
}
其结果是:
true
不幸的是,当使用:
String a=new String("Hello");
一个字符串对象在字符串常量池外创建,即使池里存在相同的字符串。考虑到这些,要避免new一个字符串除非你明确的知道需要这么做!例如:
public class Program
{
public static void main(String[] args)
{
String str1 = "Hello";
String str2 = new String("Hello");
System.out.print(str1 == str2 + " ");
System.out.print(str1.equals(str2));
}
}
结果是:
false true
JVM中有一个常量池,任何字符串至多维护一个对象。字符串常量总是指向字符串池中的一个对象。通过new操作符创建的字符串对象不指向字符串池中的任何对象,但是可以通过使用字符串的intern()方法来指向其中的某一个。java.lang.String.intern()返回一个保留池字符串,就是一个在全局字符串池中有了一个入口。如果以前没有在全局字符串池中,那么它就会被添加到里面。例如:
public class Program
{
public static void main(String[] args)
{
// Create three strings in three different ways.
String s1 = "Hello";
String s2 = new StringBuffer("He").append("llo").toString();
String s3 = s2.intern();
// Determine which strings are equivalent using the ==
// operator
System.out.println("s1 == s2? " + (s1 == s2));
System.out.println("s1 == s3? " + (s1 == s3));
}
}
输出是:
s1 == s2? false
s1 == s3? true
为了优化空间,运行时实例创建的全局字符串常量池中有一个表,总是为池中每个唯一的字符串对象维护一个引用。这就意味着它们一直引用着字符串常量池中的对象,所以,在常量池中的这些字符串不会被垃圾收集器回收。
Java语言规范第三版中的字符串常量
每一个字符串常量都是指向一个字符串类实例的引用。字符串对象有一个固定值。字符串常量,或者一般的说,常量表达式中的字符串都被使用方法 String.intern进行保留来共享唯一的实例。
package testPackage;
class Test {
public static void main(String[] args) {
String hello = "Hello", lo = "lo";
System.out.print((hello == "Hello") + " ");
System.out.print((Other.hello == hello) + " ");
System.out.print((other.Other.hello == hello) + " ");
System.out.print((hello == ("Hel"+"lo")) + " ");
System.out.print((hello == ("Hel"+lo)) + " ");
System.out.println(hello == ("Hel"+lo).intern());
}
}
class Other { static String hello = "Hello"; }
编译单元:
package other;
public class Other { static String hello = "Hello"; }
产生输出:
true true true true false true
这个例子说明了六点:
同一个包下同一个类中的字符串常量的引用指向同一个字符串对象;
同一个包下不同的类中的字符串常量的引用指向同一个字符串对象;
不同的包下不同的类中的字符串常量的引用仍然指向同一个字符串对象;
由常量表达式计算出的字符串在编译时进行计算,然后被当作常量;
在运行时通过连接计算出的字符串是新创建的,因此是不同的;
通过计算生成的字符串显示调用intern方法后产生的结果与原来存在的同样内容的字符串常量是一样的。
在理解字符串常量前,我们先熟悉一下如何创建一个字符串,在Java中有两种方法可以创建一个字符串对象:
使用new运算符。例如:
String str = new String("Hello");
使用字符串常量或者常量表达式。例如:
String str="Hello"; //(字符串常量) 或者
String str="Hel" + "lo"; //(字符串常量表达式).
这些字符串的创建方式之间有什么区别呢?在Java中,equals方法被认为是对象的值进行深层次的比较,而操作符==是进行的浅层次的比较。equals方法比较两个对象的内容而不是引用。==两侧是引用类型(例如对象)时,如果引用是相同的-即指向同一个对象-则执行结果为真。如果是值类型(例如原生类型),如果值相同,则执行结果为真。equals方法在两个对象具有相同内容时返回真-但是,java.lang.Object类中的equals方法返回真-如果类没有覆盖默认的equals方法,如果两个引用指向同一个对象。
让我们通过下面的例子来看看这两种字符串的创建方式之间有什么区别吧。
public class DemoStringCreation {
public static void main(String args[]) {
String str1 = "Hello";
String str2 = "Hello";
System.out.println("str1 and str2 are created by using string literal.");
System.out.println(" str1 == str2 is " + (str1 == str2));
System.out.println(" str1.equals(str2) is " + str1.equals(str2));
String str3 = new String("Hello");
String str4 = new String("Hello");
System.out.println("str3 and str4 are created by using new operator.");
System.out.println(" str3 == str4 is " + (str3 == str4));
System.out.println(" str3.equals(str4) is " + str3.equals(str4));
String str5 = "Hel" + "lo";
String str6 = "He" + "llo";
System.out.println("str5 and str6 are created by using string constant expression.");
System.out.println(" str5 == str6 is " + (str5 == str6));
System.out.println(" str5.equals(str6) is " + str5.equals(str6));
String s = "lo";
String str7 = "Hel" + s;
String str8 = "He" + "llo";
System.out.println("str7 is computed at runtime.");
System.out.println("str8 is created by using string constant expression.");
System.out.println(" str7 == str8 is " + (str7 == str8));
System.out.println(" str7.equals(str8) is " + str7.equals(str8));
}
}
输出结果为:
str1 and str2 are created by using string literal.
str1 == str2 is true
str1.equals(str2) is true
str3 and str4 are created by using new operator.
str3 == str4 is false
str3.equals(str4) is true
str5 and str6 are created by using string constant expression.
str5 == str6 is true
str5.equals(str6) is true
str7 is computed at runtime.
str8 is created by using string constant expression.
str7 == str8 is false
str7.equals(str8) is true
使用相同的字符序列而不是使用new关键字创建的两个字符串会创建指向Java字符串常量池中的同一个字符串的指针。字符串常量池是Java节约资源的一种方式。
字符串常量池
字符串的分配,和其他的对象分配一样,耗费高昂的时间与空间代价。JVM为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化。为了减少在JVM中创建的字符串的数量,字符串类维护了一个字符串池,每当代码创建字符串常量时,JVM会首先检查字符串常量池。如果字符串已经存在池中,就返回池中的实例引用。如果字符串不在池中,就会实例化一个字符串并放到池中。Java能够进行这样的优化是因为字符串是不可变的,可以不用担心数据冲突进行共享。例如:
public class Program
{
public static void main(String[] args)
{
String str1 = "Hello";
String str2 = "Hello";
System.out.print(str1 == str2);
}
}
其结果是:
true
不幸的是,当使用:
String a=new String("Hello");
一个字符串对象在字符串常量池外创建,即使池里存在相同的字符串。考虑到这些,要避免new一个字符串除非你明确的知道需要这么做!例如:
public class Program
{
public static void main(String[] args)
{
String str1 = "Hello";
String str2 = new String("Hello");
System.out.print(str1 == str2 + " ");
System.out.print(str1.equals(str2));
}
}
结果是:
false true
JVM中有一个常量池,任何字符串至多维护一个对象。字符串常量总是指向字符串池中的一个对象。通过new操作符创建的字符串对象不指向字符串池中的任何对象,但是可以通过使用字符串的intern()方法来指向其中的某一个。java.lang.String.intern()返回一个保留池字符串,就是一个在全局字符串池中有了一个入口。如果以前没有在全局字符串池中,那么它就会被添加到里面。例如:
public class Program
{
public static void main(String[] args)
{
// Create three strings in three different ways.
String s1 = "Hello";
String s2 = new StringBuffer("He").append("llo").toString();
String s3 = s2.intern();
// Determine which strings are equivalent using the ==
// operator
System.out.println("s1 == s2? " + (s1 == s2));
System.out.println("s1 == s3? " + (s1 == s3));
}
}
输出是:
s1 == s2? false
s1 == s3? true
为了优化空间,运行时实例创建的全局字符串常量池中有一个表,总是为池中每个唯一的字符串对象维护一个引用。这就意味着它们一直引用着字符串常量池中的对象,所以,在常量池中的这些字符串不会被垃圾收集器回收。
Java语言规范第三版中的字符串常量
每一个字符串常量都是指向一个字符串类实例的引用。字符串对象有一个固定值。字符串常量,或者一般的说,常量表达式中的字符串都被使用方法 String.intern进行保留来共享唯一的实例。
package testPackage;
class Test {
public static void main(String[] args) {
String hello = "Hello", lo = "lo";
System.out.print((hello == "Hello") + " ");
System.out.print((Other.hello == hello) + " ");
System.out.print((other.Other.hello == hello) + " ");
System.out.print((hello == ("Hel"+"lo")) + " ");
System.out.print((hello == ("Hel"+lo)) + " ");
System.out.println(hello == ("Hel"+lo).intern());
}
}
class Other { static String hello = "Hello"; }
编译单元:
package other;
public class Other { static String hello = "Hello"; }
产生输出:
true true true true false true
这个例子说明了六点:
同一个包下同一个类中的字符串常量的引用指向同一个字符串对象;
同一个包下不同的类中的字符串常量的引用指向同一个字符串对象;
不同的包下不同的类中的字符串常量的引用仍然指向同一个字符串对象;
由常量表达式计算出的字符串在编译时进行计算,然后被当作常量;
在运行时通过连接计算出的字符串是新创建的,因此是不同的;
通过计算生成的字符串显示调用intern方法后产生的结果与原来存在的同样内容的字符串常量是一样的。
发表评论
-
复习:强迫线程顺序执行方式
2019-01-03 23:42 1630方法1: 三个线程,t1,t2,t3,如果一定要按顺序执行, ... -
(转)不错的前后端处理异常的方法
2019-01-02 23:16 2037前言 在 Web 开发中, 我们经常会需要处理各种异常, 这是 ... -
info q的极客时间大咖说等资料下载
2018-08-15 08:40 3501info q的极客时间大咖说等资料下载,还有不少思维导图 链 ... -
CXF 客户端超时时间设置(非Spring配置方式)
2018-07-03 22:38 2258import org.apache.cxf.endpoint. ... -
(转)synchronized关键字画像:正确打开方式
2018-06-14 09:25 510https://mp.weixin.qq.com/s/b3Sx ... -
CountDownLatch的例子
2018-06-13 14:10 710public class StatsDemo { ... -
两道面试题,带你解析Java类加载机制
2018-06-12 16:29 637https://mp.weixin.qq.com/s/YTa0 ... -
Spring中获取request的几种方法,及其线程安全性分析
2018-06-11 09:03 690https://mp.weixin.qq.com/s/KeFJ ... -
内部类小结
2018-06-06 10:25 456https://mp.weixin.qq.com/s/hErv ... -
JVM虚拟机小结1
2018-06-04 20:43 5751 jps -l //列出详细的类名和进程ID 2)jps ... -
windows下自带命令行工具查看CPU资源情况等
2018-06-04 12:53 3128微软提供了不少命令行 ... -
(收藏)深入分析Java的序列化与反序列化
2018-05-30 15:21 637https://mp.weixin.qq.com/s/T2Bn ... -
apache common包中的序列化工具
2018-05-30 09:10 1860什么是序列化 我们的 ... -
JAVA8 JVM的变化: 元空间(Metaspace)
2018-05-24 22:30 986本文将会分享至今为至我收集的关于永久代(Permanent G ... -
(转)服务器性能指标(一)——负载(Load)分析及问题排查
2018-05-21 21:03 1400原创: Hollis Hollis 负载 ... -
(转)对象复用
2018-05-20 15:27 883public class Student { priv ... -
mapreduce中入门中要注意的几点
2018-05-06 08:59 695在 mapreduce中,比如有如下的词: I love b ... -
HDFS的基本操作
2018-05-02 21:47 956-mkdir 在HDFS创建目录 ... -
一个不错的开源工具类,专门用来解析日志头部的,好用
2018-05-02 20:00 789一个不错的开源工具类,专门用来解析日志头部的,好用。 http ... -
介绍个不错的RESTFUL MOCK的工具wiremock
2018-04-27 21:02 1923介绍个不错的RESTFUL MOCK的工具wiremock,地 ...
相关推荐
在Java编程语言中,字符串常量池(String Constant Pool)是一个重要的概念,它与程序的内存管理和性能优化密切相关。理解这个概念对于任何Java开发者来说都至关重要。字符串常量池是Java虚拟机(JVM)在运行时为...
第4节: 揭秘JVM字符串常量池和Java堆-01第4节: 揭秘JVM字符串常量池和Java堆-01第4节: 揭秘JVM字符串常量池和Java堆-01第4节: 揭秘JVM字符串常量池和Java堆-01第4节: 揭秘JVM字符串常量池和Java堆-01第4节: ...
为了提高效率和内存管理,Java虚拟机(JVM)引入了字符串常量池这一概念。字符串常量池是一个特殊的区域,它存储了程序中所有的字符串常量,避免了多次创建相同的字符串对象。本文将详细探讨字符串常量池的存储方式...
**StringTable(字符串常量池)详解** 在Java编程语言中,`StringTable`是一个重要的概念,它涉及到字符串对象的创建、存储以及内存管理。理解`StringTable`的工作原理对于优化程序性能和节省内存资源至关重要。 #...
Java中的字符串常量池是Java虚拟机(JVM)为了优化字符串对象的使用而设立的一个特殊区域,它存储了程序中所有的字符串字面量。在Java中,字符串是不可变的,这意味着一旦创建,就不能修改。这个特性使得字符串常量...
Java String 字符串常量池解析 Java 中的字符串常量池是一种为了提高性能和减少内存开销的机制。它是 JVM 实例化字符串常量时进行的一些优化,主要是为了减少字符串对象的创建和存储。 字符串常量池的设计思想是...
Java中的字符串常量池是Java虚拟机(JVM)为了优化字符串对象的使用而设计的一个特殊内存区域。这个池主要用于存储字符串字面量,也就是在程序中直接出现的字符串值,比如`"hello"`。其核心目的是减少内存的消耗和...
String int 字符串常量池 包装类型 函数参数 值传递引用传递 的 内存分配例子——源码 public static void fun_ref (Ref_test ref_out){ Ref_test ref_in=new Ref_test(); ref_in.s1="in"; //ref_out.s1=...
这就是为什么在IL(中间语言)代码中,我们看到的是`ldstr`指令,而不是`newObj`,因为`ldstr`加载的是已存在于字符串常量池中的字符串,而不是创建新的对象。 以提供的示例代码为例: ```csharp class Program { ...
"深入解析JVM之内存结构及字符串常量池" JVM(Java Virtual Machine)是Java语言的核心组件之一,负责将Java代码编译成机器代码并执行。JVM的内存结构是Java开发者需要了解的基础知识之一,本文将深入解析JVM之内存...
字符串常量池和intern 字符串常量池是Java语言中的一种机制,旨在节省空间和提高性能。它是一个内存区域,所有的Java类共享这个池子。字符串常量池的设计思想是为了解决字符串的频繁创建问题,减少内存开销和提高...
在实际开发中,我们还需要关注JVM的其他重要概念,如类加载机制(加载、验证、准备、解析、初始化)、类文件结构(魔数、版本号、常量池等)、垃圾回收算法(如标记-清除、复制、标记-整理、分代收集)以及执行引擎...
- **字符串字面量的处理**:当程序尝试创建一个新的字符串字面量时,JVM首先会检查字符串常量池中是否存在该字符串。如果存在,则返回已存在的字符串对象;如果不存在,则创建一个新的字符串对象并将其放入字符串...
jvm如何处理长字符串?java的classs文件中,constant_utf8_info的长度是u2,也就是说,一个字符串最长是65535个字节,但是,在本机做测试,超过这个长度的字符串也是允许的,原因是什么?
day08_03_字符串的常量池
在JDK 1.6及以前,字符串常量池位于方法区(也称为永久代),而在JDK 1.7中,随着永久代逐渐被移除,字符串常量池被移到堆中。到了JDK 1.8及以后,永久代完全消失,元空间取代了它的位置,但字符串常量池仍然存在于...
在 Java6 中,字符串常量池是放在 Perm 空间的,而从 Java7 开始,字符串常量池被移到 Heap 空间。 Perm 空间是一个固定大小的内存区域,用于存储类的元数据、方法、字段和字符串常量池等信息。当 Perm 空间接近满的...
而在第二行比较中,由于 `"hello"` 和 `"world"` 都是字符串字面量,它们会被合并成一个 `"helloworld"` 字符串字面量,这使得 `s3` 与 `"hello" + "world"` 实际上都指向字符串常量池中的同一个对象。 通过使用反...
- 字符串常量池是JVM内存中的一个特殊区域,用于存放所有的字符串字面量。当创建一个`String`对象时,如果常量池中已经存在相同内容的字符串,那么将返回该字符串的引用,而不是创建新的对象。 4. **字符串比较**...