Java值引用和对象引用区别Demo
转自:http://blog.csdn.net/gundsoul/article/details/4927404
以前就知道JAVA对象分对象引用和值引用,并且还知道8种基础数据类型,即引用时是值引用的数据类型,比如 int,short,long,byte,float,double,char,boolean,其它都是对象引用。可是其它的对象引用我一直都以为跟c 里面是一样的指针传递,直到今天才发现原来JAVA里面还是别有一番天地的。
1. 方法调用的时候,并不是类似c的指针传递,而是引用的复制
比如代码:
- void func1(List s) {
- s.add("dfdsa");
- }
- void test() {
- List<String> list = new ArrayList<String>();
- list.add("abc");
- func1(list);
- System.out.println(list.size()); // 此处结果为2
- }
以前一直以为在func1里面的s跟外面的list变量是同一个引用(暂且理解为指针好了)即在栈(stack)里面是同一个东东,这个结论无可厚非,可是看代码:
- void func(String s) {
- s += "tail";
- }
- void test() {
- String a = "abc";
- func(a);
- System.out.println(a); // 此处结果为abc
- }
经过讨论才发现,原来在stack里面a和func里面的s是完全不同的两个引用,虽然它们指向同一个堆(heap)里面的对象,之所以跟上面的代 码结果看起来不一样,只是因为String是一个非可变类(immutable),简单的说就是实例是不可被修改的。在func里面执行s += "tail";操作的时候,s这个引用已经变成指向heap里面另外一个值为"abctail"的对象了,老的s引用已经被废了,随时可以被gc回收了
2. String对象在内存中的位置
既然String是一个immutable的类,那么对于同样值的String实例,我们是可以不必重复创建的,于是就有了JVM中的String Pool的概念。简单的说,String Pool里面放着heap里面String对象的引用。看代码:
- String s = "abc";
当程序执行该代码的时候,JVM会在String Pool里面通过equal("abc")方法查找有没有现成的String对象引用,如果没有,则在heap里面创建一个String对象并将该对象的 引用保存到String Pool里面;如果有了,那么就直接返回该对象的引用。
再看一段非常类似的代码:
- String s = new String("abc");
当程序执行该代码的时候,JVM会像普通对象一样生成这个String对象,在heap里面保存,直接返回引用,并不会与String Pool交互,这样一来,String Pool的优势就没有被发挥了,怎么办呢?难道我们就不去使用new的方法创建String了吗?答案是JVM还提供了一个方 法:String.intern();来让String Pool管理这种String对象。
intern方法的工作原理是这样的:首先在heap里面创建一个完全一样的String对象,并且将该对象的引用放入String Pool中,最后返回给调用方,看代码:
- String s1=new String("abc");
- String s2=s1.intern();
- String s3="abc";
- System.out.println(s1==s2); //false
- System.out.println(s2==s3); //true
- System.out.println(s1==s3); //false
- s1引用的是heap里面的一个普通String对象,在String Pool中没有该对象的引用
- s2是heap中另一个String对象的引用,并且该对象的引用已经存在在String Pool中了
- s3在创建的时候JVM通过查找String Pool发现已经有一个同样的对象,所以直接返回给s3一个到该对象的引用
结论:我们在写JAVA代码的时候要尽量避免使用String s = new String("abc");这种方式,因为这样产生的对象并没有“注册”到String Pool中,无法被重复使用,如果已经存在这种对象了,我们可以通过使用s = s.intern();的方式重新创建对象并“注册”到String Pool中,方便后面的重复使用。
3. 深入JVM内存的划分
由于JVM对与heap和stack内存的使用有其特殊的规则,深入了解JVM是如何使用内存的,非常有助于我们在写程序的时候搞清楚自己的对象到底在什么地方,从而可以帮助我们在多线程程序和性能要求较高的程序中优化自己代码,有兴趣的同学可以参考sun的官方文档(http://java.sun.com/docs/books/jvms/second_edition/html/Overview.doc.html#1732),下面仅就部分知识做简单描述。
a. 每个线程都有自己独占的stack,里面存放的是当前线程执行的method及其局部变量
b. heap中有部分是公共区域,存放的是类实例(class instance)和已分配内存的数组(array)
c. heap中对于每个线程都有各自独立的内存区域,存放以下内容:
运行时常量池(runtime constant pool),上面提到的String Pool就属于其中的一部分
方法代码(method code),即线程要执行的方法代码
静态变量和方法(static variables and method),我们定义的static类型的变量和方法都存放在这里
更详细的描述可以参考图片:
Java值引用和对象引用区别Demo的更多相关文章
- 对C++11中的`移动语义`与`右值引用`的介绍与讨论
本文主要介绍了C++11中的移动语义与右值引用, 并且对其中的一些坑做了深入的讨论. 在正式介绍这部分内容之前, 我们先介绍一下rule of three/five原则, 与copy-and-swap ...
- C++ 右值引用与 const 关键字
C++11 新增了另一种引用:右值引用(rvalue reference),这种引用可指向右值,是使用 && 声明的.使用右值引用可以减少复制操作,延长临时对象生命周期,提升程序性能. ...
- Java中对象、对象引用、堆、栈、值传递以及引用传递的详解
Java中对象.对象引用.堆.栈.值传递以及引用传递的详解 1.对象和对象引用的差别: (1).对象: 万物皆对象.对象是类的实例. 在Java中new是用来在堆上创建对象用的. 一个对象能够被多个引 ...
- Java Object 引用传递和值传递
Java Object 引用传递和值传递 @author ixenos Java没有引用传递: 除了在将参数传递给方法(或函数)的时候是"值传递",传递对象引用的副本,在任何用&q ...
- Java中的基本类型和引用类型变量的区别
Java中的基本类型和引用类型变量的区别 学了一年多,说实话你要我说这些东西我是真说不出来是啥意思 基本类型: 基本类型自然不用说了,它的值就是一个数字,一个字符或一个布尔值. 引用类型: ...
- Java的引用和C++的指针de区别
Java的引用和C++的指针都是指向一块内存地址的,通过引用或指针来完成对内存数据的操作,就好像风筝的线轴一样,通过线轴总是能够找到风筝,但是它们在实现,原理作用等方面却有区别. (1)类型:引用其值 ...
- JVM内存划分以及值传递和引用传递的区别
Day05_SHJavaTraing_4-8-2017 一.JVM对自己的内存划分为5个区域 1.方法栈:所有的方法运行的时候进入内存 2.堆:存储的是容器和对象 3.方法和数据共享 ...
- Java中的基本数据类型和引用数据类型的区别
一.数据类型 Java中的数据类型分为两大类,基本数据类型和引用数据类型. 1.基本数据类型 基本数据类型只有8种,可按照如下分类 ①整数类型:long.int.short.byte ②浮点类型:fl ...
- PHP值传递和引用传递的区别
PHP值传递和引用传递的区别.什么时候传值什么时候传引用 (1)按值传递:函数范围内对值的任何改变在函数外部都会被忽略 (2)按引用传递:函数范围内对值的任何改变在函数外部也能反映出这些修改 (3)优 ...
随机推荐
- 你真的懂Redis的5种基本数据结构吗?
摘要: 你真的懂Redis的5种基本数据结构吗?这些知识点或许你还需要看看. 本文分享自华为云社区<你真的懂Redis的5种基本数据结构吗?这些知识点或许你还需要看看>,作者:李子捌. 一 ...
- JVM核心——JVM运行和类加载全过程
1.类加载全过程 (1)类加载机制 JVM把class文件加载到内存,并对数据进行校验.解析和初始化,最终形成JVM可以直接使用的Java类型的过程. 加载 将class文件字节码内容加载到内存中,并 ...
- vue3 学习笔记 (五)——vue3 的 setup 如何实现响应式功能?
setup 是用来写组合式 api ,内部的数据和方法需要通过 return 之后,模板才能使用.在之前 vue2 中,data 返回的数据,可以直接进行双向绑定使用,如果我们把 setup 中数据类 ...
- CentOS编译openjdk
编译openjdk 1. 下载openjdk源码 openjdk的官网是OpenJDK (java.net) 在网站左侧就能看到它的源码位置的链接 从图上可以看到,它的源码在两个位置有托管,Mercu ...
- FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅲ
第三波,走起~~ FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅰ FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅱ 单位根反演 今天打多校时 1002 被卡科技了 ...
- dotnet 将自动代码格式化机器人带入团队 GitLab 平台
给团队带入一个 代码格式化机器人 能提升团队的幸福度,让团队的成员安心写代码,不用关注代码格式化问题,将格式代码这个粗活交给机器人去做.同时也能减少在代码审查里撕格式化问题的时间,让更多的时间投入到更 ...
- 【豆科基因组】大豆(Soybean, Glycine max)泛基因组2020Cell
目录 一.前沿概述 二.主要结果 重测序.组装与注释 泛基因组 SV特征 PAV与古多倍化,WGD事件 基因SV与基因融合 SV与大豆驯化 SV影响基因表达及其与性状关联 一.前沿概述 Pan-Gen ...
- python-django 模板的抽象和继承
{% include %}只需要一句即可,不需要end***
- pyspider爬虫框架的安装和使用
pyspider是国人binux编写的强大的网络爬虫框架,它带有强大的WebUI.脚本编辑器.任务监控器.项目管理器以及结果处理器,同时支持多种数据库后端.多种消息队列,另外还支持JavaScript ...
- 巩固java第六天
巩固内容: HTML 空元素 没有内容的 HTML 元素被称为空元素.空元素是在开始标签中关闭的. <br> 就是没有关闭标签的空元素(<br> 标签定义换行). 在 XHTM ...