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. Keil5生成bin文件

    进入“Options for Target”设置界面如下: 如图所示方框中输入: fromelf.exe --bin -o "$L@L.bin" "#L" 生成 ...

  2. WPF常见内存泄露

    Event handlers leak This type of leak occurs when subscribing an object (let's call it listener) to ...

  3. ARTS 12.24 - 12.28

    从陈皓博主的专栏里学到一个概念,争取可以坚持下去: 每周一个 Algorithm,Review 一篇英文文章,总结一个工作中的技术 Tip,以及 Share 一个传递价值观的东西! 一个 Algori ...

  4. LigerUI中Grid的使用时关于url请求不到数据的问题

    前台代码:(这里贴的是js的代码,完整的代码可以在LigerUI的文档中找到), 这里使用的是url请求数据,问题不是处在前台,所以就不细说. $("#maingrid").lig ...

  5. NSTimer 的简易使用方法

      一.使用方式 1.声明NSTimer方法   static CGFloat sIntervalTime = 15.f; //定时刷新时间间隔 @property (nonatomic, stron ...

  6. NPOI 超简单的导出导入

      首先说说,第一次遇到过匿名导出的那个时候是在我在北京第一家公司,简单的声明一个对象就可以导出,那时候感觉高大上,自己也想研究研究,但是因为头将代码后来加密了根本看不到.好吧,研究了研究放弃了,后来 ...

  7. IIS6.0 WEB园配置

    为应用程序池创建 Web 园请注意以下几点: 一.每一个工作进程都会消耗系统资源和CPU占用率:太多的工作进程会导致系统资源和CPU利用率的急剧消耗: 二.每一个工作进程都具有自己的状态数据,如果We ...

  8. asp.net mvc+jquery easyui开发实战教程之网站后台管理系统开发1-准备工作

    /****** Object: 新闻表 Script Date: 2017/9/2 星期六 15:11:12 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENT ...

  9. vuejs切换导航条高亮路由高亮做法

    我的GitHub前端经验总结,喜欢的话请点star✨✨Thanks.:https://github.com/liangfengbo/frontend-develop vuejs导航条高亮我的做法: 用 ...

  10. 我整理的一份来自于线上的Nginx配置(Nginx.conf),希望对学习Nginx的有帮助

    我整理了一份Nginx的配置文件说明,是真正经历过正式线上考验过.如果有优化的地方,也请朋友们指点一二,整理出一份比较全而实用的配置. 主要包含配置:负载均衡配置,页面重定向,转发,HTTPS和HTT ...