java栈与堆的区别,队列,数组,链表集合的介绍,java 参数传递是值传递,数组和String作为参数传递的区别,string赋值方式的区别

java栈与堆的区别,队列,数组,链表集合的介绍,java 参数传递是值传递,数组和String作为参数传递的区别,string赋值方式的区别

根据链接点击打开链接得到的总结:

由java基本类型byte,int,short,long float,double,boolean,char 这八种定义的变量,在java为了追求速度是直接在栈中为期分配内存空间的,不是类的引用.在栈中有个”数据共享”的特性,比如,定义一个int a=3,栈会定义一个变量为a的引用,如果栈中一开始没有3,则栈会开辟一个存放字面值为3的地址.当再定义一个int b=3,栈会创建变量为b的引用,但是栈中已经有了一个字面值为3的地址,所以会出现a和b同时指向3的情况.

java把内存分为两部分,一部分栈内存,一部分是堆内存,在函数中定义的一些基本类型的变量和对象都是在栈内存中分配的,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。

而堆内存是用来存储new创建的对象和数组,其内存分配是由java虚拟机的自动垃圾回收器管理,在堆中产生了一个数组或对象之后,可以在栈中定义一个特殊的变量,让这个变量的值是数组或对象在堆内存的首地址,栈的这个变量变成了堆中的数组或对象的引用变量.以后就可以使用栈的引用变量来访问对的数组或对象.引用变量在运行到其作用域之外便被释放,而堆中的数组和对象直到没有变量引用他的时候才会变成垃圾被回收.

栈堆是先进后出,可以使用链表或数组表示,

队列是先进先出,只能在对尾添加数据,队头删除数据,但是,可以查看队头和队尾的数据,还有双端队列,在两端都可以插入和删除,可以用链表和数组表示。

数组:连续的内存空间保存数据,

链表:是在非连续的内存单元中保存数据。

集合:

collection是最基本的集合接口,list和set继承了collectin.map没有

list是有序的collection ,list能够精确的控制每个元素的插入位置

实现list接口的常见类有arraylist,linkedlist,vector,stack,

java 参数传递是值传递还是引用传递,数组和String作为参数传递的区别:

总结一下几点:1:Java参数传递方式只有一种,就是按值传递。

2:如果传入方法的是基本类型的东西,你就得到此基本类型的一份拷贝。如果是传递引用,就得到引用的拷贝。

3:String属于引用传递,但是它很特殊,在参数传递时它是重新new了一个String,导致前后的引用地址发生改变,在方法中改变的是新new的String的值。而原先的并没有改变。有很多朋友说string是不可变类型的,大概就是这个意思吧!

4:在堆内存的垃圾自动回收机制是:当创建的堆内存空间没有栈引用指向它的时候,系统会认为这个块区域变为垃圾,JAVA的自动垃圾回收机制会在适当的时候释放这块空间

下面我们具体说下值传递,首先是基本类型:为了加快程序运行速度,java创建基本类型a=4,首先会创建变量为a的引用,然后会先去栈中查找有4,就把4的地址付给a,也就是a直接指向4。如果没有4就创建4,在把4的地址赋值给a。

java栈与堆的区别,队列,数组,链表集合的介绍,java 参数传递是值传递,数组和String作为参数传递的区别,string赋值方式的区别

上图就是,在栈中创建一块变量为a的区域并为其非配地址,然后指向4.

如果在使用如下:

a=4;

f(a);

把a当做入参的时候只是把上图的4放到了方法中,并不是a的地址,在f()方法跟a是没有关系的。

当我们创建一个对象的时候,如:

Dog dog=new Dog();

上面这个其实是分为两部分的。java等号赋值运算是先执行右边再执行赋值运算给左边。右边是在堆中创建一块局域存放新对象dog,然后看左边是在栈中创建变量为dog的引用地址,赋值后执行堆中创建的dog区域。

java栈与堆的区别,队列,数组,链表集合的介绍,java 参数传递是值传递,数组和String作为参数传递的区别,string赋值方式的区别

当dog对象作为参数传递时:f(dog)

public void f(Dog dog){};

会在栈中拷贝一份dog,二者指向的堆内存地址是一样的,当我们再f()方法中修改dog的属性变量值时,也就是修改上图的堆内存中new Dog()的内容,同时也修改之前的对象的内容。

java栈与堆的区别,队列,数组,链表集合的介绍,java 参数传递是值传递,数组和String作为参数传递的区别,string赋值方式的区别

那么当是string的时候有什么不同呢?

String 是一种特殊的对象。因为string用的比较多,因此它在堆内存中有常量池的概念。

最明显的是我们创建string变量的方式大都是:String a=”aa”;咋一看不是基础类型创建的方式吗?其实它是在堆内存中有个aa,然后栈的a变量的引用地址指向它,如下:

java栈与堆的区别,队列,数组,链表集合的介绍,java 参数传递是值传递,数组和String作为参数传递的区别,string赋值方式的区别

当string变量作为参数传递时,

String a=”a”;

f(a);

public void f(String b){

b=“aa”;

}

System.out.println(a);

这段代码打印的结果还是a,因为string的特性,这里小编也不知到底层代码是怎样的。先记住吧!可以认为其实执行的过程等价于一下代码:

public void f(String b){

String b2=new String(b);

b2=”aa”;

}

这里有个new ,就知道又在堆中创建了一块区域,这块区域只有b2指向它,a指向的还是它自己的堆内存,所以a的值没有改变。

最后我们看一个常见的值传递的面试题:

public static void f(char[] ch2,String str2){
		ch2[2]='g';
		str2="dd";
	}

	public static void main(String[] args) {
		
		char[] ch={'a','b','c'};
		String str="abc";
		f(ch, str);
		System.out.println(str);
		for(char c:ch){
			System.out.print(c);
		}

结果是:

abc
abg

这个题表达的就是string与对象值传递的区别。虽然这里是数组,其实跟对象是一样的,数组的元素可认为是对象的属性字段,类比下就行了。数组跟string类型经过f方法赋值后,数组的内容改变了,但是string的没有变。原因就是上面介绍的,数组改变的同一块堆内存。而string因为重新创建了一个对象,改变的值不是同一个堆内存,所以值没有变。

下面我们顺带介绍下:

Java中String类通过new创建和直接赋值字符串的区别

方式一:String a = “aaa” ;

方式二:String b = new String(“aaa”);

  • 两种方式都能创建字符串对象,但方式一要比方式二更优。
  • 因为字符串是保存在常量池中的,而通过new创建的对象会存放在堆内存中。

一:常量池中已经有字符串常量”aaa”

  • 通过方式一创建对象,程序运行时会在常量池中查找”aaa”字符串,将找到的”aaa”字符串的地址赋给a。
  • 通过方式二创建对象,无论常量池中有没有”aaa”字符串,程序都会在堆内存中开辟一片新空间存放新对象。

一:常量池中没有字符串常量”aaa”

  • 通过方式一创建对象,程序运行时会将”aaa”字符串放进常量池,再将其地址赋给a。
  • 通过方式二创建对象,程序会在堆内存中开辟一片新空间存放新对象,同时会将”aaa”字符串放入常量池,相当于创建了两个对象。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/106353.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • eclipse怎么配置svn插件_dip插件有哪几种

    eclipse怎么配置svn插件_dip插件有哪几种Eclipse安装插件的几种方法(eclipse安装SVN插件)在这里啰嗦一句,其实更新的版本mar2更好用。但是由于在低电压版的本本上,mar2跑不起来,经常假死,kepler可以很流畅。 so,如果为了携带了轻便低电压版CPU的本本,mar2跑不起来,就用kepler吧。以Eclipse(Kepler)安装SVN插件为例,记录eclipse安装插件的几种方法。 1eclipsemarket…

    2022年10月10日
    0
  • 【引用】回发或回调参数无效。在配置中使用 <pages enableEventValidation=”true”/>(转载)…「建议收藏」

    【引用】回发或回调参数无效。在配置中使用 <pages enableEventValidation=”true”/>(转载)…「建议收藏」回发或回调参数无效。在配置中使用<pagesenableEventValidation=”true”/>或在页面中使用<%@PageEnableEventValidation=”true”%>启用了事件验证。出于安全目的,此功能验证回发或回调事件的参数是否来源于最初呈现这些事件的服务器控件。如果数据有效并且是预期的,则使用ClientScriptM…

    2022年7月24日
    4
  • 手机发布版sha1怎么获取_androidstudio导出项目zip

    手机发布版sha1怎么获取_androidstudio导出项目zip申请key必须用发布版的SHA1及MD51.打包出来apk;2.将apk修改后缀为.rar文件后解压;3.进入解压后的META-INF目录,该目录下会存在文件CERT.RSA;4.在该目录下打开cmd,输入命令:keytool-printcert-fileCERT.RSA若提示输入密码,则输入android后回车…

    2022年8月10日
    3
  • word2016论文不同章节设置页眉页码方法[通俗易懂]

    word2016论文不同章节设置页眉页码方法[通俗易懂]最近在写硕士论文需要调整页眉页脚,并且每一章都不一样,网上搜的教程都有点复杂,现在自己弄懂了,把它记录下来:1,设置不同章节不同页眉2,设置奇偶页不同2,设置页码从第xx页开始本文以word2016为例,讲述以上3点的设置方法:1,设置不同章节不同页眉首先是常规操作,点击word上方插入–页眉和页码这样页眉和页码就在word上显示出来了然而仅这样操作所有…

    2025年7月3日
    0
  • C语言学习——位运算

    C语言学习——位运算原码反码补码介绍原码 就是前面所介绍的二进制定点表示法,即最高位为符号位,“ 0 ”表示正,“ 1 ”表示负,其余位表示数值的大小。反码 表示法规定:正数的反码与其原码相同;负数的反码是对其原码逐位取反,但符号位除外。补码 表示法规定:正数的补码与其原码相同;负数的补码是在其反码的末位加 1 。补码详细介绍补码是为了表示一个负数的二进制形式。其转化方式是,先将负数当成正数,转化成二进制…

    2022年8月18日
    3
  • vue根据下标获取数组中的值_document.getElementBy

    vue根据下标获取数组中的值_document.getElementBy关于<Element*at0x******>如何查看标签中的数据fromlxmlimportetreeimportrequestsurl=’https://www.pearvideo.com/’#首页地址data={}headers={“User-Agent”:”Mozilla/5.0(WindowsNT10.0;Win64;x64)””AppleWebKit/537.36(K

    2022年9月4日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号