java 字符常量池
一、题目:
问题:String str = new String(“hello”),“hello”在内存中是怎么分配的? 答案是:堆,字符串常量区。
Java中的字符串常量池和JVM运行时数据区的相关概念。"hello"为字面量对象,其存储在堆内存中。而字符串常量池则存储的是字符串对象的一个引用。
二、Java中的字符串常量池
Java中字符串对象创建有两种形式:
1.字面量形式: 如 String str = "droid";
2.使用new这种标准的构造对象的方法,如 String str = new String("droid");
这两种方式我们在代码编写时都经常使用,尤其是字面量的方式,然而这两种实现其实存在着一些性能和内存占用的差别。这一切都是源于JVM为了减少字符串对象的重复创建。
三、工作原理
当代码中出现字面量形式创建字符串对象时,JVM首先会对这个字面量进行检查,如果字符串常量池中存在相同内容的字符串对象的引用,则将这个引用返回,否则新的字符串对象被创建,然后将这个引用放入字符串常量池,并返回该引用,Java能够进行这样的优化是因为字符串是不可变的,可以不用担心数据冲突进行共享。
四、举例说明
package testDemo;
public class test1 {
public static void main(String[] args) {
String st1="hello";
String st2="hello";
System.out.println(st1==st1);
}
}
其结果是:
true

JVM首先检测hello 这个字面量,通过字符串常量池查找不到内容为hello的字符串对象存在,所以创建这个字符串对象,然后将刚创建的对象的引用放入到字符串常量池中,并且将引用返回给变量str1。

同样JVM还是要检测这个字面量,JVM通过查找字符串常量池,发现内容为”hello”字符串对象存在,于是将已经存在的字符串对象的引用返回给变量str2,注意这里不会重新创建新的字符串对象。
使用new创建

当我们使用了new来构造字符串对象的时候,不管字符串常量池中有没有相同内容的对象的引用,新的字符串对象都会创建。
因此我们使用下面代码测试一下

结果返回:flase 表明这两个变量指向的为不同的对象。
使用intern
对于上面使用new创建的字符串对象,如果想将这个对象的引用加入到字符串常量池,可以使用intern方法。 调用intern后,首先检查字符串常量池中是否有该对象的引用,如果存在,则将这个引用返回给变量,否则将引用加入并返回给变量。

输出结果为true
五、疑难问题
前提条件
1.字符串常量池实现的前提条件就是Java中String对象是不可变的,这样可以安全保证多个变量共享同一个对象。如果Java中的String对象可变的话,一个引用操作改变了对象的值,那么其他的变量也会受到影响,显然这样是不合理的。
2.字符串常量池中存放的是引用还是对象,这个问题是最常见的。字符串常量池存放的是对象引用,不是对象。在Java中,对象都创建在堆内存中。
优缺点
优:字符串常量池的好处就是减少相同内容字符串的创建,节省内存空间。
缺:如果硬要说弊端的话,就是牺牲了CPU计算时间来换空间。CPU计算时间主要用于在字符串常量池中查找是否有内容相同对象的引用。不过其内部实现为HashTable,所以计算成本较低。
GC回收
因为字符串常量池中持有了共享的字符串对象的引用,这就是说是不是会导致这些对象无法回收?首先问题中共享的对象一般情况下都比较小。据我查证了解,在早期的版本中确实存在这样的问题,但是随着弱引用的引入,目前这个问题应该没有了
java 字符常量池的更多相关文章
- 触摸java常量池
java常量池是一个经久不衰的话题,也是面试官的最爱,题目花样百出,小菜早就对常量池有所耳闻,这次好好总结一下. 理论 小菜先拙劣的表达一下jvm虚拟内存分布: 程序计数器是jvm执行程序的 ...
- Java 线程池框架核心代码分析--转
原文地址:http://www.codeceo.com/article/java-thread-pool-kernal.html 前言 多线程编程中,为每个任务分配一个线程是不现实的,线程创建的开销和 ...
- Java线程池使用说明
Java线程池使用说明 转自:http://blog.csdn.net/sd0902/article/details/8395677 一简介 线程的使用在java中占有极其重要的地位,在jdk1.4极 ...
- (转载)JAVA线程池管理
平时的开发中线程是个少不了的东西,比如tomcat里的servlet就是线程,没有线程我们如何提供多用户访问呢?不过很多刚开始接触线程的开发攻城师却在这个上面吃了不少苦头.怎么做一套简便的线程开发模式 ...
- Java线程池的那些事
熟悉java多线程的朋友一定十分了解java的线程池,jdk中的核心实现类为java.util.concurrent.ThreadPoolExecutor.大家可能了解到它的原理,甚至看过它的源码:但 ...
- Java数据库连接池封装与用法
Java数据库连接池封装与用法 修改于抄袭版本,那货写的有点BUG,两个类,一个用法 ConnectionPool类: package com.vl.sql; import java.sql.Conn ...
- 几个主流java连接池
池(Pool)技术在一定程度上可以明显优化服务器应用程序的性能,提高程序执行效率和降低系统资源开销.这里所说的池是一种广义上的池,比如数据库连接池.线程池.内存池.对象池等.其中,对象池可以看成保存对 ...
- Java连接池详解
于共享资源,有一个很著名的设计模式:资源池(Resource Pool).该模式正是为了解决资源的频繁分配﹑释放所造成的问题.为解决我们的问题,可以采用数据库连接池技术.数据库连接池的基本思想就是为数 ...
- Java数据库连接池
转载过来的,最近在做一个小网站,准备使用这种方法. Java jdbc数据库连接池总结! 1. 引言 近年来,随着Internet/Intranet建网技术的飞速发展和在世界范围内的迅速普及, ...
随机推荐
- 【Unity技巧】统一管理回调函数——观察者模式
这次的内容有点类似设计模式里的观察者模式.但是和常规意义上的观察者模式也不是完全一致,所以各位就不要咬文嚼字啦!咦?设计模式?!不懂!没关系,说不定你以前就用过. 开场白 我们来想象一个场景.在加载一 ...
- Cocos2D v2.0至v3.x简洁转换指南(二)
触摸处理 我们在稍后将完成Cocos2d 3.0中触摸处理的完整教程.而现在最重要的是知道如何去启用触摸处理在你的CCNode中: self.userInteractionEnabled = TRUE ...
- Mysql数据库安装和配置
http://blog.csdn.net/pipisorry/article/details/46773507 Mysql数据库安装和配置.mysql语法.特殊符号及正则表达式的使用.MySQL备份与 ...
- Android应用---基于NDK的samples例程hello-jni学习NDK开发
Android应用---基于NDK的samples例程hello-jni学习NDK开发 NDK下载地址:http://developer.android.com/tools/sdk/ndk/index ...
- Android中处理大图片时图片压缩
1.BitmapFactory.Options中的属性 在进行图片压缩时,是通过设置BitmapFactory.Options的一些值来改变图片的属性的,下面我们来看看BitmapFactory.Op ...
- Linux权限与命令间的关系
极重要!权限与命令间的关系: 我们知道权限对於使用者帐号来说是非常重要的,因为他可以限制使用者能不能读取/创建/删除/修改文件或目录! 在这一章我们介绍了很多文件系统的管理命令,第六章则介绍了很多文件 ...
- HBase集群部署脚本
#!/bin/bash # Sync HBASE_HOME across the cluster. Must run on master using HBase owner user. HBASE_H ...
- OpenCV实现图像物体轮廓,前景背景,标记,并保存。
#include <iostream> // for standard I/O #include <string> // for strings #include <io ...
- javascript、ruby和C性能一瞥(2)
好吧,最后让我们用C来实现,看看再能榨取多少性能.注意我没有改变算法,C的算法和之前的3种都是基本相同的: #include <stdio.h> #include <stdlib.h ...
- OpenCV手写数字字符识别(基于k近邻算法)
摘要 本程序主要参照论文,<基于OpenCV的脱机手写字符识别技术>实现了,对于手写阿拉伯数字的识别工作.识别工作分为三大步骤:预处理,特征提取,分类识别.预处理过程主要找到图像的ROI部 ...