问题一:

String str1 = "abc";

String str2 = "abc";

System.out.println(str1==str2); //true

问题二:

String str1 =new String ("abc");

String str2 =new String ("abc");

System.out.println(str1==str2); // false

问题三:

String s1 = "ja";

String s2 = "va";

String s3 = "java";

String s4 = s1 + s2;

System.out.println(s3 == s4);//false

System.out.println(s3.equals(s4));//true

由于以上问题让我含糊不清,于是特地搜集了一些有关java内存分配的资料,以下是网摘:

Java 中的堆和栈

Java把内存划分成两种:一种是栈内存,一种是堆内存。

在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。

当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。

堆内存用来存放由new创建的对象和数组。

在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。

在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。

引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。

具体的说:

栈与堆都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。

Java的堆是一个运行时数据区,类的(对象从中分配空间。这些对象通过new、newarray、anewarray和multianewarray等指令建立,它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。

栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量(,int, short, long, byte, float, double, boolean, char)和对象句柄。

栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:

int a = 3;

int b = 3;

编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着处理int b = 3;在创建完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。这时,如果再令a=4;那么编译器会重新搜索栈中是否有4值,如果没有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b, 它是由编译器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。

String是一个特殊的包装类数据。可以用:

String str = new String("abc");

String str = "abc";

两种的形式来创建,第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。

而第二种是先在栈中创建一个对String类的对象引用变量str,然后查找栈中有没有存放"abc",如果没有,则将"abc"存放进栈,并令str指向”abc”,如果已经有”abc” 则直接令str指向“abc”。

比较类里面的数值是否相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象时,用==,下面用例子说明上面的理论。

方式一:

String str1 = "abc";

String str2 = "abc";

System.out.println(str1==str2); //true

可以看出str1和str2是指向同一个对象的。

方式二:

String str1 =new String ("abc");

String str2 =new String ("abc");

System.out.println(str1==str2); // false

用new的方式是生成不同的对象。每一次生成一个。

因此用第一种方式创建多个”abc”字符串,在内存中其实只存在一个对象而已. 这种写法有利与节省内存空间. 同时它可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。

另一方面, 要注意: 我们在使用诸如String str = "abc";的格式定义类时,总是想当然地认为,创建了String类的对象str。担心陷阱!对象可能并没有被创建!而可能只是指向一个先前已经创建的对象。只有通过new()方法才能保证每次都创建一个新的对象。由于String类的immutable性质,当String变量需要经常变换其值时,应该考虑使用StringBuffer类,以提高程序效率。

java查看内存地址_Java内存机制和内存地址相关推荐

  1. java jvm内存模型_Java(JVM)内存模型– Java中的内存管理

    java jvm内存模型 Understanding JVM Memory Model, Java Memory Management are very important if you want t ...

  2. .NET中的内存管理,GC机制,内存释放过程

    引言:作为一个.NET程序员,我们知道托管代码的内存管理是自动的..NET可以保证我们的托管程序在结束时全部释放,这为我们编程人员省去了不少麻烦,我们可以连想都不想怎么去管理内存,反正.NET自己会保 ...

  3. java栈的回收_JAVA的堆栈和内存、垃圾回收解说

    1.有关java健壮性特点的真相 很多书上都说java健壮性的特点是因为java使用数组代替了c++的指针:c++最令人头痛的问题就是内存问题,java的健壮性使编程人员不用再考虑内存的问题:这种观点 ...

  4. java查看jvm对象个数_jmap-查看 jvm 内存对象信息

    jmap 概述 命令jmap是一个多功能的命令. 它可以生成 java 程序的 dump 文件,也可以查看堆内对象示例的统计信息.查看 ClassLoader 的信息以及 finalizer 队列. ...

  5. java的gc策略_Java的GC与内存分配策略

    资料整理来源以及参考: Java的GC机制主要针对于 堆以及方法区 而言,对于程序计数器,虚拟机栈,本地方法栈三个区域是随着线程而生,随线程而灭的,栈中的栈帧随着方法的进入和退出有条不紊的执行出栈和入 ...

  6. java 虚拟机内存类_java 虚拟机类加载 及内存结构

    在面试java工程师的时候,这道题经常被问到,故需特别注意. 1.JVM 简介 JVM 是我们Javaer 的最基本功底了,刚开始学Java 的时候,一般都是从"Hello World &q ...

  7. java避免内存泄露_Java防止非静态内部类内存泄漏

    内存泄漏 一个不会被使用的对象,因为另一个正在使用的对象持有该对象的引用,导致它不能正常被回收,而停留在堆内存中,从而导致内存泄漏. 最坏的情况下,由于大量的内存泄漏,最终导致jvm的内存耗尽,致使程 ...

  8. java二维数组 内存分配_java中二维数组内存分配

    区分三种初始化方式: 格式一: 数据类型[][] 数组名 = new 数据类型[m][n]; m:表示这个二维数组有多少个一维数组. n:表示每一个一维数组的元素有多少个. //例:int arr[] ...

  9. java 内存 四_java最终化的内存保留问题(4)

    四. 一种代替最终化的选择 在前面一节中的示例还存在一种不确定性可能:JVM并不能保证它在最终化队列中调用对象的终结器的顺序.而来自于所有类(应用程序,库,等等)的终结器都是被同等对待的.因此,一个占 ...

  10. java jar 最大内存大小_Java运行Jar包内存配置的操作

    Java运行Jar包内存配置的操作,内存,大小,空间,最小,这是 Java运行Jar包内存配置的操作 易采站长站,站长之家为您整理了Java运行Jar包内存配置的操作的相关内容. 如下: java - ...

最新文章

  1. ACMNO.23 C语言-素数判定 写一个判断素数的函数,在主函数输入一个整数,输出是否是素数的消息。 输入 一个数 输出 如果是素数输出prime 如果不是输出not prime
  2. golang web 框架 gin beego iris 对比
  3. JSBinding+SharpKit / 菜单介绍
  4. 【数字信号处理】相关函数 ( 卷积与交换性 | 相关函数不具有交换性 | 推导过程 )
  5. sscanf操作字符串和整型的区别
  6. OpenGL 坐标系统(Perspective)
  7. SpringMVC中跳转路径的问题
  8. 「万字干货」高并发系统分析与大型互联网架构介绍
  9. 欢乐鼠标自动点击器_使用ESP32 DIY蓝牙自动点击器,滑屏器
  10. NOIP模拟测试26「嚎叫响彻在贪婪的机房·主仆见证了 Hobo 的离别·征途堆积出友情的永恒」...
  11. 关于MATLAB2014b不能并行计算的原因及解决方法
  12. foobar插件_如何为 caddy 添写自定义插件
  13. python基础教程免费下载-《Python机器学习基础教程》高清版免费PDF下载
  14. python模拟抛硬币_python模拟抛硬币
  15. 精彩回顾 | NDBC 2021华为参会回顾
  16. 阿里云服务器ECS操作系统有哪些版本?
  17. telnet登录交换机
  18. 你这一生其实只有9年
  19. CUDA入门和网络加速学习(二)
  20. Access violation reading location 0x000000XX

热门文章

  1. 2018半年总结:走过的路
  2. 存在量词后必须用合取式?-数学
  3. tf.variance_scaling_initializer() tensorflow学习:参数初始化
  4. logging.basicConfig函数
  5. 聚类Clustering
  6. 基于Jittor框架实现LSGAN图像生成对抗网络
  7. “ compiler-rt”运行时runtime库
  8. 构建可扩展的GPU加速应用程序(NVIDIA HPC)
  9. Darknet_Yolov3模型搭建
  10. 2021年大数据Hive(一):​​​​​​​Hive基本概念