Java中对象的内存分配问题
2016-03-22 21:06
423 查看
1.先看一下一下程序代码:
输出结果如下:
2.查询了一下资料,得到关键字“==”存在如下特性:
基本数据类型(也称原始数据类型):byte,short,char,int,long,float,double,boolean。他们之间的比较,应用双等号(==),比较的是他们的值。
复合数据类型(类):当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址(确切的说,是堆内存地址)。
注:对于第二种类型,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。因为每new一次,都会重新开辟堆内存空间。
3.结论如下:
Java中对象主要存储在堆栈(有时简称栈)和堆中。一般用new关键字,会将新建的对象存储在堆中,因此以上的程序实例中,两个new String对象并不相等,但对于基本数据类型,例如
对于非new创建出来的变量,Java会在其字符串常量池(仍位于堆中)创建字符集,然后将对象指向该字符集,当字符串常量池中已有某个字符集时,再次创建“值”相同的对象,指向与前一对象的指向是相同的,这也就是为什么上面两个int和String对象输出都是true。
4.关于引用传递,先看如下代码:
输入如下:
引用传递的本身是值传递,但这里实际传递的是对象的hashcode,关于hashcode的资料摘抄如下:
hashCode是指对象的散列码,具体值是由对象的hashCode()方法返回的值,,你甚至可以重写该方法让每个对象的hashCode都一样。散列码一般是和HashTable HashMap这种基于散列码的集合有用,用于提高在集合中查询对象的速度。
而内存地址是对象在内存中的位置,一般和hashCode无关。不过Object对象的hashCode方法是个native方法,有可能和对象的内存地址有关。
对
由此可以看到,Java引用可以改变实参的内容,但是不能改变实参对象本身。这可以通过以下代码来说明。对
输出如下:
可以看到,传入的对象没有得到改变。
public class MyClass { public static void main(String[] args) { String s1 = new String("Hello World!"); String s2 = new String("Hello World!"); String s3 = "Hello World!"; String s4 = "Hello World!"; int t1 = new Integer(1); int t2 = new Integer(1); int t3 = 1; int t4 = 1; System.out.println("两个new String对象:" + (s1 == s2)); System.out.println("两个String对象:" + (s3 == s4)); System.out.println("两个new Interger对象:" + (t1 == t2)); System.out.println("两个int对象:" + (t3 == t4)); } }
输出结果如下:
两个new String对象:false 两个String对象:true 两个new Interger对象:true 两个int对象:true
2.查询了一下资料,得到关键字“==”存在如下特性:
基本数据类型(也称原始数据类型):byte,short,char,int,long,float,double,boolean。他们之间的比较,应用双等号(==),比较的是他们的值。
复合数据类型(类):当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址(确切的说,是堆内存地址)。
注:对于第二种类型,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。因为每new一次,都会重新开辟堆内存空间。
3.结论如下:
Java中对象主要存储在堆栈(有时简称栈)和堆中。一般用new关键字,会将新建的对象存储在堆中,因此以上的程序实例中,两个new String对象并不相等,但对于基本数据类型,例如
boolean,char,byte,short,int,long,float,double等数据类型,Java采用与C和C++相同的方法,不用new来创建变量,而是创建一个并非是引用的“自动变量”,这个变量直接存储“值”,并置于堆栈中,使得这种小的、简单的变量效率变高,这也就是上面的程序实例中,两个new int对象相等,输出为true。
对于非new创建出来的变量,Java会在其字符串常量池(仍位于堆中)创建字符集,然后将对象指向该字符集,当字符串常量池中已有某个字符集时,再次创建“值”相同的对象,指向与前一对象的指向是相同的,这也就是为什么上面两个int和String对象输出都是true。
4.关于引用传递,先看如下代码:
public class ManTest { int age; String name; ManTest() { this.age = 0; this.name = null; } ManTest(int age,String name) { this.age = age; this.name = name; } public void ShowInfo() { System.out.println("姓名:" + this.name + ";年龄:" + this.age); } public void ChangeInfo( ManTest man) { man.age = 10; man.name = "小明"; } public static void main(String args[]) { ManTest man = new ManTest(15,"小红"); man.ShowInfo(); man.ChangeInfo(man); System.out.println("改变后--------------"); man.ShowInfo(); } }
输入如下:
姓名:小红;年龄:15 改变后-------------- 姓名:小明;年龄:10
引用传递的本身是值传递,但这里实际传递的是对象的hashcode,关于hashcode的资料摘抄如下:
hashCode是指对象的散列码,具体值是由对象的hashCode()方法返回的值,,你甚至可以重写该方法让每个对象的hashCode都一样。散列码一般是和HashTable HashMap这种基于散列码的集合有用,用于提高在集合中查询对象的速度。
而内存地址是对象在内存中的位置,一般和hashCode无关。不过Object对象的hashCode方法是个native方法,有可能和对象的内存地址有关。
对
ChangeInfo函数进行修改,使其输出对象的hashcode值,输出如下,可以看到两者的hashcode是完全相同的:
姓名:小红;年龄:15 传入方法前:1669472530 传入方法后:1669472530 改变后-------------- 姓名:小明;年龄:10
由此可以看到,Java引用可以改变实参的内容,但是不能改变实参对象本身。这可以通过以下代码来说明。对
ChangeInfo函数和
main函数进行如下修改:
public void ChangeInfo( ManTest man) { System.out.println("传入方法后:" + man.hashCode()); man = new ManTest(10,"小明"); System.out.println("改变对象后:" + man.hashCode()); System.out.println("在类体的方法中,姓名:" + this.name + ";年龄:" + this.age); } public static void main(String args[]) { ManTest man = new ManTest(15,"小红"); man.ShowInfo(); System.out.println("传入方法前:" + man.hashCode()); man.ChangeInfo(man); System.out.println("改变后--------------"); man.ShowInfo(); }
输出如下:
传入方法前:2065827189 传入方法后:2065827189 改变对象后:1989444474 在类体的方法中,姓名:小红;年龄:15 改变后-------------- 姓名:小红;年龄:15
可以看到,传入的对象没有得到改变。
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android之获取手机上的图片和视频缩略图thumbnails
- android string.xml文件中的整型和string型代替
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- Python动态类型的学习---引用的理解
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序