`

值传递与引用传递

阅读更多
一、值传递与引用传递

其实按值还是按引用的区别在于“是否在传递的时候进行对象的内存拷贝”,
java中基本类型是由于在JVM中存储区域不同于普通对象所以传递前会拷贝,传递的是拷贝后的值,
但是对象在传递的时候不拷贝,直接传“引用值”,指向同一片对象堆内存区域

二、基本数据类型

public class IntegerTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		int a = 10 ;
		Integer b = new Integer(10);
		IntegerTest test = new IntegerTest();
		test.change(a);
		test.change(b);
		System.out.println(a);
		System.out.println(b);
	}

	public int change(Integer a){
		a = a + 10 ;
		return a ;
	}
}



输出结果:
10
10

基本数据类型
main() 方法向 change() 中传递的是 栈中a 所存储的内容 10
change() 方法,形参 a ,虽然与 main() 中,名称相同,但是两个不同的变量


对应的包装类
// Integer 的 value 是 final 修饰的
    /**
     * The value of the <code>Integer</code>.
     *
     * @serial
     */
    private final int value;

其底层实现中value是final修饰,是不可改变的
与String 类似,其值是不可变更的

若欲通过change() 修改数值:
通过change()的返回值,重新赋值给 main()中的a

结论:
基本数据类型及对应的包装类在传递过程中,不会改变其所指向的内容


三、String 类型

public class StringChangeTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		String str = "abc" ;
		new StringChangeTest().change(str);
		System.out.println(str);
	}

	public void change(String str){
		str = "bcd";
	}
}



字符串只要赋值就相当于新new一个对象,字符串变量指向这个新new的对象,之前的对象就成了没有引用指向的对象了。

1.String 的两种声明方式

String str = "abc"
栈中建立 str
判断堆中是否已有"abc",无则创建新的匿名空间,存放 "abc"
匿名空间首地址存放在 str 中,即 str 指向堆中的此空间

String str = new String("abc")
栈中建立 str
判断堆中是否已有"abc",无则创建新的匿名空间,存放 "abc"
堆中开辟新的空间,存放 "abc"
新的空间首地址存放在 str 中,匿名空间因无引用,过后被GC回收

备注:
提高程序运行效率,优选第一种方式

2.
String str = "abc" ;
未显示调用 new 操作,在编译时 相当于 new String("abc");

3.
change(String str);
此处的str 不同于 main() 中的 str ,相当于重新开辟了一个空间,虽然名称相同
调用方法时,main() 方法将 str = "abc" 的堆空间地址传递给了 change() 中的str
此时 main() change() 中的两个不同的 str 均指向同一个堆内存块

但 str = "bcd" ; 相当于 在堆中新开辟了一块空间,存放 "bcd",并将地址存放在了str 中
即 change() 中的 str 指向了新的堆中的地址 -- "bcd" 的地址,与 main() 中的 str 指向的 "abc" 无关了,在 change() 中对 str 的修改,也与 main() 中无关,所以值没有改变

四、引用类型

public class ArrayIntegerTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		int [] a1 = {1,2,3,4,5};
		new ArrayIntegerTest().change(a1);
		for(int i = 0 ; i < a1.length ; i++){
			System.out.println(a1[i]);
		}
		
		int [] a12 = new int[]{1,2,3,4,5};
		new ArrayIntegerTest().change(a12);
		for(int i = 0 ; i < a12.length ; i++){
			System.out.println(a12[i]);
		}
		
		Integer [] a2 = {1,2,3,4,5};
		new ArrayIntegerTest().change(a2);
		for(int i = 0 ; i < a2.length ; i++){
			System.out.println(a2[i]);
		}
		
		char [] s1 = {'1','2','3'};
		new ArrayIntegerTest().change(s1);
		System.out.println(new String(s1));
	}

	public void change(int[] a){
		a[0] = 10 ;
	}
	
	public void change(Integer[] a){
		a[0] = 10 ;
	}
	
	public void change(char[] a){
		a[0] = 'a';
	}
}




main() 中,建立引用对象,在堆中开辟新的空间
change() 中,形参声明新的对象,与main的不同
main() 调用 change() 时,将 栈中存放的堆中空间的首地址传递给 change() 中的参数
两者指向同一个数据地址
所以,change() 中的操作影响 main() 中的数据内容

public class PersonTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		Person p = new Person();
		p.setAge(10);
		
		new PersonTest().change(p);
		System.out.println(p.getAge());
	}

	public void change(Person p){
		p.setAge(20);
		
		p = new Person();
		p.setAge(30);
	}
}

class Person{
	private int age ;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	
	
}


输出:20

调用 change() ,与 main() 中 p 是两个不同的句柄,但此时指向同一个堆中的地址
setAge(20) 有效
重新new 一个p ,此时 change() 中的 p 与 main() 的 p 指向的堆中的地址已经不一样了
new 新开辟空间,一定与之前的不同
所以 setAge(30) 对 main() 中的无影响

分享到:
评论

相关推荐

    第04章 面向对象(上) 08 值传递与引用传递

    本章节主要探讨的是在面向对象编程中一个重要的概念:值传递与引用传递。理解这两个概念对于编写高效、安全的Java程序至关重要。 值传递是指当函数或方法调用时,参数的副本被传入到函数内部。这意味着在函数内部对...

    java值传递与引用传递

    因此,尽管看似是引用传递,但对`String`类型的处理结果与值传递类似。 总结来说,Java中的参数传递主要有以下特点: 1. 基本数据类型按值传递,函数内部无法改变实际参数的值。 2. 引用类型看似按引用传递,实际上...

    数组总结(概念、定义、默认值、可变长参数、值传递与引用传递等)

    数组总结(概念、定义、默认值、可变长参数、值传递与引用传递等)。1.冒泡排序: ​ 两两相比(两个相邻的数进行比较) 条件成立 互换位置 ​ 外层循环控制比较的轮数 **轮数永远是 长度 -1 (n - 1)** ​ 内层循环...

    值传递和引用传递

    #### 四、值传递与引用传递的区别 - **数据类型**:值传递通常用于基本数据类型(如int、double等),而引用传递则用于对象类型(如类实例)。 - **内存分配**:值传递时,系统会为形参分配新的内存空间;而引用传递...

    值传递与引用传递-内存解析

    与值传递不同,引用传递不创建参数值的副本,而是让函数直接访问原始变量。这样,函数对参数的任何操作都会反映到原始变量上。在C++中,引用是一个别名,它指向一个已存在的对象。在Python中,对象是通过引用传递的...

    面向对象语言中的值传递与引用传递

    面向对象编程语言中,参数传递主要有两种方式:值传递和引用传递。这两种方式在Java这样的语言中有着明显的区别,理解它们对于编写高效、无误的代码至关重要。 **值传递**: 值传递是Java中处理基本数据类型(如int...

    Java:按值传递还是按引用传递详细解说

    ### Java中的按值传递与按引用传递详解 #### 一、引言 在Java编程语言中,关于参数传递的方式一直存在两种观点:一种认为Java仅支持按值传递,另一种则指出Java同时支持按值传递和按引用传递。实际上,这两种观点...

    值传递,指针传递,引用传递的区别,内含可运行代码和详细解释

    另一方面,值传递由于形参和实参内存地址不一样,有些功能并不能实现(swap()),因此,除了极为简单的函数会使用值传递外,大多数会采用引用传递。而对于指针传递,则在涉及数组的情况下使用较多,因为指针本身会给...

    java 值传递和引用传递的比较

    在Java编程语言中,了解值传递和引用传递的概念至关重要,因为它们直接影响到函数参数的处理方式。下面将详细探讨这两个概念及其区别。 首先,我们来理解什么是值传递。在Java中,基本数据类型(如int、double、...

    论JS函数传参时:值传递与引用传递的区别

    首先讨论函数之前,先弄清楚基本类型值与引用类型值的复制问题 一、数据类型的复制分析 内存分为栈区(stack)和堆区(heap) ,如果将内存看成一本书,栈好比是书的目录,而堆就是书的内容,基本类型可以看成内容...

    JAVA参数传递方式实例浅析【按值传递与引用传递区别】

    JAVA 参数传递方式实例浅析【按值传递与引用传递区别】 JAVA 参数传递方式实例浅析【按值传递与引用传递区别】是 JAVA 编程语言中的一种基本概念,对于 JAVA 开发者来说是非常重要的。本文将通过实例形式分析 JAVA ...

    Java中的值传递和引用传递的区别.doc

    ### Java中的值传递与引用传递详解 #### 一、引言 在Java编程语言中,了解参数传递的方式对于深入理解程序的行为至关重要。根据传递的数据类型不同,Java中有两种主要的参数传递方式:值传递(Value Passing)和...

    java 之方法调用 方法传参 值传递还是引用传递字节码

    本文将深入探讨Java中的方法调用、值传递与引用传递,并通过字节码分析来进一步理解这些概念。 首先,我们来看方法调用。在Java中,方法是一组完成特定任务的代码块,可以通过方法名来调用执行。方法调用的基本语法...

    Java面向对象值传递和引用传递

    Java 面向对象值传递和引用传递 Java 面向对象编程中,参数传递是非常重要的一个概念。参数传递有两种方式:值传递和引用传递。了解这两种方式的区别是非常重要的,因为它们对程序的执行结果产生了很大的影响。 值...

    LabVIEW中引用的概念及在VI间传递值

    在VI间传递值,通常有三种方式:按值传递、按引用传递和按共享变量传递。按值传递是最常见的,但会创建数据副本,可能导致性能下降。相比之下,按引用传递能避免这种问题,因为只有引用本身被传递,而不是实际数据。...

    引用和对象的关系,还有值传递

    值传递与引用传递 在Java中,无论是基本类型还是对象引用都是通过值传递的方式进行的。例如: ```java void changeValue(Vehicle v) { v = new Vehicle(); v.passengers = 4; } ``` 在上述例子中,即使改变了...

    C#笔记值传递和引用传递

    在C#编程语言中,了解值传递和引用传递的概念至关重要,因为这直接影响到函数或方法如何处理参数。本文主要探讨这两个概念以及与之相关的知识点。 首先,值传递是指当一个方法或函数调用时,实际参数(即调用时提供...

    Delphi值传递和引用传递实例

    Delphi,作为一款基于Pascal语法的面向对象的编程环境,提供了两种主要的参数传递机制:值传递(ByValue)和引用传递(ByReference)。这两者在处理函数或方法的参数时有着显著的区别,对程序性能和数据安全有直接...

    java值传递和引用传递详解

    Java中的参数传递方式主要有两种:值传递和引用传递。理解这两种机制是编程中至关重要的,因为它们直接影响到函数内部如何改变或操作传入的数据。 **值传递**在Java中是基本数据类型(如int, double, char等)的...

Global site tag (gtag.js) - Google Analytics