String会出现在哪些地方

  • 方法内的局部string
  • 类内的字段String
  • static string
  • 容器中存储的string
  • String数组

    那么String的位置会影响其存储方式吗?

    显然是不会的,类永远只会储存在堆上。

    但是实际上类的字段并不是一直在堆上的。

String的构造方法

以下来自String类 源码,一些无关紧要的实现被我省略了:

 private final char value[];
private int hash; // Default to 0
private static final long serialVersionUID = -6849794470754667710L;
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
public String() {
this.value = "".value;
}
public String(String original) {
this.value = original.value;//底层char[]指向了同一位置!
this.hash = original.hash;
}
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);//底层char[]指向不同位置!下面的截取也是如此
}
public String(char value[], int offset, int count) { ... } public String(int[] codePoints, int offset, int count) {...} public String(byte ascii[], int hibyte, int offset, int count) {...} public String(byte ascii[], int hibyte) {...}

我们可以发现String的构造器并不关注是否将char[]指向同一位置,之所以有一些没有指向同一位置完全是为了保证char[]是immutable的。

这并不能说明调用构造器构造的String的内存位置有什么特别之处。

String另一种构造方式--为包装类型提供的专有构造方式

运行如下代码:

class StringPointerTest{
String g="gh",h="gh";
}
public class StringTest {
public static void main(String[] args) {
String a="abc";
String b="abc";
System.out.println(a==b);//true使用简写的构造能够复用创建的string类
String c=new String("abc");
System.out.println(a==c);//false是用构造器则不能
String d=new String("def");
String e="def";
System.out.println(d==e);//false即使先构造器再使用简化构造也不行。
StringPointerTest spt=new StringPointerTest();
System.out.println(spt.g==spt.h); //true与String的属于方法局部变量还是类字段也无关
}
}
class IntegerPointTest1{
Integer a=1; }
class IntegerPointTest2{
Integer b=1;
}
public class IntegerTest {
public static void main(String[] args) {
System.out.println(new IntegerPointTest1().a==new IntegerPointTest2().b);//true!
}
}

原理

需要存储的代码元素有:

  • Class类文件
  • 方法,类的所以实例应该共用一段方法
  • static字段
  • 字符串常量
  • 值常量
  • 类实例
  • 各种引用
  • 基本变量

    他们各自有各自的存储位置,方法内的引用存在方法栈,类内的引用存在堆,类存储在堆上,方法中的局部基本变量存于栈但是类字段的基本变量存在堆上(方法区内)。

    值得一提的是方法区(又叫静态区),其存储值常量、字符串常量、方法、静态字段、.class文件,等只用一个备份的数据。

    栈和方法区都有共享数据的功能。

    因此使用简化方法构造String类的时候,在方法内和类内会将字符串存于栈/方法区,这无关紧要,重要的是,

    使用这种构造方法,如果没有所构造的字符串常量存在于内存中,那么会在栈/方法区中存上一份,然后再堆中新建一个String类,把String类的char[]引用指向在栈/方法区中的字符串常量;

    如果所构造的字符串常量已经存在于内存中,那么则会检索关联与之对应的堆中String实例,并直接使用这个String类实例。

    只有使用简化方法构造才能被栈/方法区记录下来,如果使用new则不行,这也是为什么上例即使先new,再使用简化构造相同字符串也不会引用相同。

    因为new出来的String实例的字符串常量存储在堆上,和栈/方法区无关。

拓展到所有包装类型---可以吗?

完全不可以。

他们都没有像String那样实现缓存。

但是实现了类似的缓存,它们的自动包装机制也提供缓存功能,

但是是基于valueof方法的,该方法会对一定范围内进行缓存。

而且实现方式非常暴力,是在对应类里存一个静态的类数组,并静态初始化全部填充。

可以缓存的范围:

byte Byte -128–127

short Short -128–127

int Integer -128—127

long Long -128—127

char Character 0–127

boolean Boolean TURE,FALSE

String

不缓存的:

float Float

double Double

可见不是所有的自动包装机制都实现了全缓存。

String到底在内存中是如何存储的的更多相关文章

  1. C语言中float,double类型,在内存中的结构(存储方式)

    C语言中float,double类型,在内存中的结构(存储方式)从存储结构和算法上来讲,double和float是一样的,不一样的地方仅仅是float是32位的,double是64位的,所以doubl ...

  2. @清晰掉 C++ 中的 enum 结构在内存中是怎么存储的?

     C++ 中的 enum 结构在内存中是怎么存储的? C++ C++ 中的 enum 结构在内存中是怎么存储的?里面存储的是常量值吗?   关于占用内存的大小,enum类型本身是不占内存的,编译器直接 ...

  3. float数据在内存中是怎么存储的 AND IEEE754测试程序

    float类型数字在计算机中用4个字节存储.遵循IEEE-754格式标准: 一个浮点数有2部分组成:底数m和指数e 底数部分 使用二进制数来表示此浮点数的实际值指数部分 占用8bit的二进制数,可表示 ...

  4. 代码演示C#中string和StingBuilder内存中的区别

    关于 string和StringBuilder的区别参考MSDN.本文用程序演示它们在内存中的区别,及其因此其行为不同. //Demo  string memory model namespace C ...

  5. C# CLR via 对象内存中堆的存储【类型对象指针、同步块索引】

    最近在看书,看到了对象在内存中的存储方式. 讲到了对象存储在内存堆中,分配的空间除了类型对象的成员所需的内存量,还有额外的成员(类型对象指针. 同步块索引 ),看到这个我就有点不懂了,不知道类型对象指 ...

  6. 牛客网Java刷题知识点float数据在内存中是怎么存储的

    不多说,直接上干货! float类型数字在计算机中用4个字节存储. 遵循IEEE-754格式标准: 一个浮点数有2部分组成:底数m和指数e (1)底数部分 使用二进制数来表示此浮点数的实际值 (2)指 ...

  7. js的数组在内存中是如何存储的

    前言:本来想自己总结下,但发现以下文章已经写得很好,就直接放链接了. 英文文章:http://voidcanvas.com/javascript-array-evolution-performance ...

  8. Java语言中:float、double数据类型在内存中是如何存储的

    引用参考 https://www.cnblogs.com/chenmingjun/p/8415464.html#4291528 https://blog.csdn.net/yansmile1/arti ...

  9. JavaScript中的变量在内存中的具体存储形式

    栈内存和堆内存 JavaScript中的变量分为基本类型和引用类型 基本类型是保存在栈内存中的简单数据段,它们的值都有固定的大小,保存在栈空间,通过按值访问 引用类型是保存在堆内存中的对象,值大小不固 ...

随机推荐

  1. 财富500强的前10个公司里有8个公司在使用Qt(Qt自己认为的优点是:直觉主义、跨平台、节省时间),以及一些商业案例

    8 of Top 10 Fortune 500 use Qt Qt is the software development framework of choice by engineers in ov ...

  2. 零元学Expression Blend 4 - Chapter 4元件重复运用的观念

    原文:零元学Expression Blend 4 - Chapter 4元件重复运用的观念 本章将教大家Blend元件重复运用的观念,这在Silverlight设计中是非常重要的,另外加码赠送渐层工具 ...

  3. 有未经处理的异常(在 xx.exe 中): 堆栈 Cookie 检测代码检测到基于堆栈的缓冲区溢出。

    一般这个问题是数组越界. 我产生这个异常的代码是这句:memcpy(tmp_cert.byKey, m_row[2], 255); 255的长度超过了char数组tmp_cert.byKey的长度.

  4. git服务器创建,冲突解决,远程仓库获取指定文件

    1.git服务器创建 在公司多人协作开发的情况下,不能简单地使用github,因为github是互联网公开的,这种情况公司的代码的保密性就会丧失了.这种情况下,需要创建git服务器. 登录服务器,使用 ...

  5. Android零基础入门第42节:自定义BaseAdapter

    原文:Android零基础入门第42节:自定义BaseAdapter 在ListView的使用中,有时候还需要在里面加入按钮等控件,实现单独的操作.也就是说,这个ListView不再只是展示数据,也不 ...

  6. 使用Chart控件进行实时监控

    Chart作为微软提供绘制图表的控件,在刚开始使用时非常的迷茫,因为功能强大,涉及到的知识多, 一开始难以接收过来,但后天经过查找资料,耐心学习,终于还是有了一定的收获. Chart相当于一个大的图纸 ...

  7. 广义线性模型(Generalized Linear Model)

    广义线性模型(Generalized Linear Model) http://www.cnblogs.com/sumai 1.指数分布族 我们在建模的时候,关心的目标变量Y可能服从很多种分布.像线性 ...

  8. MSYS2 瘦身小攻略(使用junction)

    MSYS2, 吃硬盘的大神 MSYS2,集成了 x86 x64两个开发环境,且可以使用 pacman 进行包管理,可谓方便的很!可是,这个东东也有一个很不好的地方,就是实在太占硬盘.尽管下载的软件包一 ...

  9. WebRequest请求错误(服务器提交了协议冲突. Section=ResponseHeader Detail=CR 后面必须是 LF)

    WebRequest请求错误(服务器提交了协议冲突. Section=ResponseHeader Detail=CR 后面必须是 LF)解决办法,天津config文件,增加一个配置如下 <?x ...

  10. Qt之QGraphicsEffect阴影、模糊效果

    Qt之QGraphicsEffect阴影.模糊效果 Qt之QGraphicsEffect阴影模糊效果 效果图 阴影和模糊效果 正常效果 代码 customshadoweffecth customsha ...