最近在自学java基础,由于嵌入式以后的就业前景不是很好,加上自己本学期学习了51单片机发现自己对硬件不是很在行,可能是因为初中以来物理一直不是很好吧,导致自己现在一看到电路板,电压电阻电流都会产生一种恐惧感,就像大三现在的我对与数据结构也有一种畏难情绪(不愿意花很多时间去研究,很多时候数据结构都和数学逻辑有关,但数据结构真的很重要,大家在大学一定要好好学数据结构,以后对你自己编程会有很大帮助)。。

由于自己学了很长时间的C(记得那时候对指针很感兴趣花了很多课外时间去研究)加上自己本学期学过汇编,涉及到底层。所以每学一门新的语言就会分析它的内存分配问题。

好吧,闲扯了几句,我最近碰到一个很有趣的问题,关于String str = “123” 和String str =new String(“123”); 分析它的内存分配。。。

在分析上面那个问题之前我们先来补充下JAVA的一些预备知识:

JAVA中的内存区划分

栈区:保存基本数据类型(引用),对象的引用

堆区:保存每个对象的具体属性

全局数据区:保存static类型的属性

全局代码区:保存所有方法的定义

常量区:字符常量区(“111”、”112”...)和基本数据常量区(1、2.2...)及其他

接下来举个简单的例子-》 贴代码:

Class Test

{

Public static int num = 0;  //统计实例化了多少该类的对象

Private int a; Public Test(int a){   This.a = a; Num++;   }

Public void printA(){ System.out.println(a); }

}

Public class TestDemo

{

Public static void main(String arg[])

{

int a = 1;

int b = 1;

Test t1= new Test(1);

t1.printA();

}

}

为了更直观我画了几个图,可能比文字描述更直观。。

在画图之前,我们先来说下java文件的编译过程。。

.java(java文件)经过编译(在dos界面通过javac.exe借助于jdk编译,或者一些IDE自带的编译器编译)  ----》》》》.class字节码文件在通过jdk中的java虚拟机(jvm)对.class字节码文件在不同的操作系统上  ------》》》运行(关于虚拟机jvm的作用这里不做具体解释,自行百度哈哈哈)

好了上图吧(由于是画图板请点击放大查看)

好了,认真看完上文(扯了这么多。。)

就来分析下String str = “123” 和String str =new String(“123”)的内存分配问题吧。

想要了解一个问题,我们得进入到String内中看它的原型(关于如何看源码一种是看API还一种是自己在调试的时候进入String内后面这种方式得自行百度有详细的步骤)

 public final class String

implements java.io.Serializable, Comparable<String>, CharSequence {

/*进入到这是不是有点想起C了,莫名的亲切 */

private final char value[];//加了final关键字说明不可string字符串不可改变

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(Stringoriginal) {

this.value =original.value;

this.hash =original.hash;

}

public String(char value[]) {

this.value = Arrays.copyOf(value,value.length);

}

这里重点说两个问题:一个是private final char value[]说明了String类中并没有给字符串的内存分配空间只是分配了一个final char* 指针

二是String类的构造函数 public String(String original)

public String(char value[]),当String str = new String(“xxx”);时是调用那个构造函数呢。

接下来上代码

按F11进行调试,F5进入String构造函数

注意看调用了public String(Stringoriginal)构造函数,而且是value值之间的相互赋值...

所以到了这里可以简单画一个内存分析图了

分析::string str1 =“123”,如果string池之前没有”abc”对象就现在str池实例化一个”abc”对象,然后str1引用指向它。。(假设这时候在来一句string copyStr1=”abc”, 就同时指向了对象”abc”了)思考一下这样做的目的其实是java为了节约内存,只在第一次的时候分配内存然后后面如果有其他的引用指向相同的字符串对象就只需要在栈区分配一个引用的空间了。。是不是很赞(可以用System.out.println(str1==copyStr1))验证为True

说明指向的是同一块空间

String str2 = new String(“abc”);在堆区分配对象的内存然后在调用构造函数将”abc”.value的值赋值给str2对象的value,它们是不同的对象(可以用System.out.println(str1==str2)验证为False),但它们的value值是相同的都是指向同一个字符串常量”abc”;

综上所述:String类虽然叫字符类,但String只是一个包装类,并没有为字符串分配空间去存取它们,只留了一个value值去指向字符串常量

所以:虽然string str1 = “123” 和String str2 = new String(“abc”);能达到相同的目的,但是出于内存节约的原则,建议用前者,给堆区节省内存

补充一点关于String池:这部分内存应该在堆区jvm自动分配的,有些书上会写成匿名(String类)对象,这部分内存应该是有java自己的(GC- java回收机制)自己去回收。。。

留一个问题:假如你去面试java有关的工作,技术官问你

string str1 = “123” 和String str2 = new String(“abc”);分别分配了几次内存???仔细想想

最后关于补充两个小问题:

1>>>JAVA中int a = 1和int b = 1的内存分配我发表一下自己看法(可能不正确)

我们在C 语言中我们知道这肯定是分配了两个int的内存然后值都为1,而且我们输出a和b的地址 并且a和b的地址不相同。(自己用vs、vc++试验一下)这里就不截图了

但是由于java中没有指针的概念不能与内存直接沟通,所以这里没法验证地址

但是这里有一个很有趣问题或许可以给我们启发:在C语言中比如直接定义int a;然后输出a结果是个垃圾值。。。但是在java中如果没有赋初值输出的时候会编译报错

我们是不是可以这样想,既然要输出a的值,编译器可能要去常量区找值,结合开头我们提到,a指向常量值(保存某个常量值的地址)这里未初始化,也就是说a没有存地址,这时候编译运行的时候发现a没有地址就不知道怎么去常量区取值了(这只是个人猜想,有待我自己翻阅资料验证)。

2>> 关于str1 = str1 +“xxx” 以及   字符串比较的问题

我们不是说String类一旦确定就不能改变的么(string语言中有一个value加了final关键字,代表value的指向字符串不可以改变)

上一个代码:

输出结果如下,(自己可以尝试画画内存图,分析一下)

我们进入"123abc".equals(str1)的源码:

红色框框里面的是不是很熟悉?其实就是我们C语言里很简单的字符串比较

但是为什么第一个输出为false呢?我们可以推测如果直接==的话应该是比较对象地址的值,也就是引用的值,你想一下str1和匿名对象”123abc”在堆栈不同的内存块中,肯定不相等是吧。。附上我自己画的很丑的图

基于上图的内存分析图:我们可以得知用str1 = str1 + “abc”,在堆中又重新分配了一块堆内存(虽然后面GC会自动回收但还是浪费了堆内存)所以我们不建议这么做(自己可以看java书,用StringBuffer类比较合适)。

结尾:

好了就说这么多了,由于这是本人第一次写博客,文笔不是很好所以语言组织的可能有点杂乱(个人觉得写博客是一件很酷的事情,可以把自己想法传到博客和别人分享)所以一定会有很多地方写的不够专业,用的词语也不像一些大神很术语,所以如果各位读者看到了有什么错误,或者觉得有疑问,和自己平时的认知有冲突的,可以在下面留言板给我留言,大家一起交流,一起进步----祥子留

关于String str1 = “123“ 和 String str2 = new String(“123“)内存分析相关推荐

  1. 【C++ 语言】C++字符串 ( string 类 | 创建方法 | 控制台输出 | 字符串操作 | 栈内存字符串对象 | string* )

    文章目录 C++ 字符串 对象 C++ 字符串 对象 创建方法 C++ 字符串 对象 输出到控制台 C++ 字符串 拼接 C++ 字符串 方法调用 ( 栈内存对象 ) C++ 字符串 方法调用 ( 堆 ...

  2. string修饰的梦修改吗_Java String 对象,你真的了解了吗?

    String 对象的实现 String对象是 Java 中使用最频繁的对象之一,所以 Java 公司也在不断的对String对象的实现进行优化,以便提升String对象的性能,看下面这张图,一起了解一 ...

  3. Java String到int,Java int到String

    Today we will look at Java String to int conversion and then java int to String conversion. Java pro ...

  4. JavaSE学习总结(八)常用类(上)Object类==与equals方法的区别浅克隆的特点Scanner类String类String两种创建对象方式的区别String类的各种功能

    JavaSE学习总结(八)常用类(上)/Object类/==与equals方法的区别/浅克隆的特点/Scanner类/String类/String两种创建对象方式的区别/String类的各种功能 常用 ...

  5. java中将string类型转int类型或者将string类型转long类型方法(亲测)

    将字串 String 转换成整数 int 两种方法: 1).int i = Integer.parseInt("111"); 或 i = Integer.parseInt([Str ...

  6. python string模块template_Python标准库笔记(1) — string模块

    String模块包含大量实用常量和类,以及一些过时的遗留功能,并还可用作字符串操作. 1. 常用方法 常用方法描述str.capitalize()把字符串的首字母大写str.center(width) ...

  7. 在拦截器中获取请求参数,[Ljava.lang.String; cannot be cast to java.lang.String报错

    Map<String,Object> parametersmap=invocation.getInvocationContext().getParameters();//获取请求参数    ...

  8. java string 反序列化_如何将java.lang.String的空白JSON字符串值反序列化为null?

    我正在尝试使用简单的JSON反序列化为Java对象.不过,我,让空 字符串 值,java.lang.String属性值.在其余的属性中,空白值将转换为 空 值(这是我想要的). 我的JSON和相关的J ...

  9. C++string类常用函数 c++中的string常用函数用法总结

    string类的构造函数: string(const char *s);    //用c字符串s初始化 string(int n,char c);     //用n个字符c初始化 此外,string类 ...

最新文章

  1. 这款IDEA插件刷爆了朋友圈,网友:这用起来有点酸爽~
  2. 【Fourier Convolution】傅里叶卷积
  3. List,Set,Collection,Collections比较
  4. l2_norm opencv torch比较
  5. 求职特训营火热来袭 阿里大咖教你制作专业简历
  6. IOS手机关于音乐自动播放问题的解决办法
  7. Linux shell 常用命令
  8. 继续发布分页类的BLL层和Interface层部分哈
  9. nyoj 456 邮票分你一半【01背包】
  10. post postman 传递数组对象_okhttp传递数组参数
  11. 16.卷2(进程间通信)---Sun RPC
  12. 中国工程院院士郑纬民:应鼓励从头研发先进的存储系统软件
  13. 【数学建模】7 线性规划及例题详解
  14. DroidCam---将手机转为电脑外接摄像头的软件(提供下载链接)
  15. cad剪裁地形图lisp_CAD怎么在完整地形图里截取需要的部分地形图
  16. onion浏览器下载_洋葱浏览器最新下载_洋葱浏览器官方版 - 软件帝
  17. 【转】编写高质量代码改善C#程序的157个建议——建议33:避免在泛型类型中声明静态成员...
  18. 重庆大学计算机学院小学期安排,2019年重庆大学寒假放假时间安排是什么 重庆大学2019年学校校历如何安排...
  19. apache评分条件_APACHE Ⅲ 评分标准.doc
  20. 怎么申请学校邮箱?学校邮箱格式有哪些?

热门文章

  1. 恒大健康5亿收购电动汽车驱动系统研发商e-Traction
  2. Go 语言 exec 实时获取外部命令的执行输出
  3. 深度技术 GHOST XP SP3 快速装机专业版 V2013.03
  4. delphi编写dll
  5. 龙芯杯系统能力竞赛CPU赛道参赛准备
  6. 【手撕算法】FMM图像修复算法C++实现
  7. Java单体应用 - 架构模式 - 03.设计模式-10.装饰器模式
  8. 来源(Provenance)介绍
  9. 人脸识别9-人脸搜索(概述)
  10. php 下一年,php获取一年有多少天