【java】值传递和引用传递理解

 一、理解

★ 当一个变量最为一个参数传入方法内部的时候,会有两种不同的传递方式:值传递和引用传递。

  ☆ 值传递的特点:不管方法内部对传进去的参数作任何改变,也不会影响方法外部的变量的值

  ☆ 引用传递的特点:方法内部对传进去的参数作的改变也会影响方法外部的变量的值

二、记忆

1、基本类型(8种)的传递都是值传递

2、引用类型(除String外)都是引用传递(传递引用的副本)

3、Strng比较特殊,它虽然是引用类型,但是却是值传递

三 示例

3.1 基本类型:如 int

 

Java代码 复制代码 收藏代码
  1. public class StudyInt {
  2. public static void main(String[] args) {
  3. new StudyInt().printFirst();
  4. }
  5. private void printFirst() {
  6. int i = 2;
  7. testChange(i);
  8. System.out.println("printFirst:i = "+i);
  9. }
  10. private void testChange(int i) {
  11. i = 4;
  12. System.out.println("testChange: i = "+i);
  13. }
  14. }
public class StudyInt {
	public static void main(String[] args) {
		new StudyInt().printFirst();
	}
	private void printFirst() {
		int i = 2;
		testChange(i);
		System.out.println("printFirst:i = "+i);
	}
	private void testChange(int i) {
		i = 4;
		System.out.println("testChange: i = "+i);
	}
}

打印结果:

testChange: i = 4
printFirst:i = 2

理解:

i 作为参数将值传递给testChange方法,不论值在testChange 中怎么变,都不影响 i 在printFirst中的值

3.2 引用类型:如 新建Appoint类

 

Java代码 复制代码 收藏代码
  1. public class StudyAppoint {
  2.  
  3. public static void main(String[] args) {
  4. new StudyAppoint().printFirst();
  5. }
  6. private void printFirst() {
  7. Appoint iAppoint = new Appoint();
  8. sysoutAppoint("1 初始值:printFirst", iAppoint);
  9.  
  10. testChange(iAppoint);
  11. sysoutAppoint("2 传参更改值:printFirst", iAppoint);
  12. // 重点testNew方法传递的是引用的副本,当改变副本的指向地址时,原属性本身的值不改变
  13. testNew(iAppoint);
  14. sysoutAppoint("3 传参new对象:printFirst", iAppoint);
  15. // 重点理解testChangeAndNew
  16. testChangeAndNew(iAppoint);
  17. sysoutAppoint("4 传参改值并new对象:printFirst", iAppoint);
  18. }
  19. private void testChange(Appoint iAppoint) {
  20. iAppoint.iInt = 2;
  21. iAppoint.iStr = "testChange";
  22. sysoutAppoint("testChange", iAppoint);
  23. }
  24. private void testNew(Appoint iAppoint) {
  25. Appoint i = new Appoint();
  26. i.iInt = 3;
  27. i.iStr = "testChangeNew";
  28. iAppoint = i;
  29. sysoutAppoint("testNew", iAppoint);
  30. }
  31. private void testChangeAndNew(Appoint iAppoint) {
  32. iAppoint.iInt = 4;
  33. iAppoint.iStr = "testChangeAndNew 1";
  34. Appoint i = new Appoint();
  35. i.iInt = 5;
  36. i.iStr = "testChangeNew 2";
  37. iAppoint = i;
  38. sysoutAppoint("testChangeAndNew", iAppoint);
  39. }
  40. /**
  41. * 打印出执行的方法中指定的属性的值
  42. */
  43. private void sysoutAppoint(String methodName, Appoint iAppoint) {
  44. System.out.println(methodName + ":iAppoint.iInt = " + iAppoint.iInt);
  45. System.out.println(methodName + ":iAppoint.iStr = " + iAppoint.iStr);
  46. }
  47. }
  48.  
  49. class Appoint {
  50. int iInt = 1;
  51. String iStr = "aaa";
  52. }
public class StudyAppoint {

	public static void main(String[] args) {
		new StudyAppoint().printFirst();
	}
	private void printFirst() {
		Appoint iAppoint = new Appoint();
		sysoutAppoint("1 初始值:printFirst", iAppoint);

		testChange(iAppoint);
		sysoutAppoint("2 传参更改值:printFirst", iAppoint);
		// 重点testNew方法传递的是引用的副本,当改变副本的指向地址时,原属性本身的值不改变
		testNew(iAppoint);
		sysoutAppoint("3 传参new对象:printFirst", iAppoint);
		// 重点理解testChangeAndNew
		testChangeAndNew(iAppoint);
		sysoutAppoint("4 传参改值并new对象:printFirst", iAppoint);
	}
	private void testChange(Appoint iAppoint) {
		iAppoint.iInt = 2;
		iAppoint.iStr = "testChange";
		sysoutAppoint("testChange", iAppoint);
	}
	private void testNew(Appoint iAppoint) {
		Appoint i = new Appoint();
		i.iInt = 3;
		i.iStr = "testChangeNew";
		iAppoint = i;
		sysoutAppoint("testNew", iAppoint);
	}
	private void testChangeAndNew(Appoint iAppoint) {
		iAppoint.iInt = 4;
		iAppoint.iStr = "testChangeAndNew 1";
		Appoint i = new Appoint();
		i.iInt = 5;
		i.iStr = "testChangeNew 2";
		iAppoint = i;
		sysoutAppoint("testChangeAndNew", iAppoint);
	}
	/**
	 * 打印出执行的方法中指定的属性的值
	 */
	private void sysoutAppoint(String methodName, Appoint iAppoint) {
		System.out.println(methodName + ":iAppoint.iInt = " + iAppoint.iInt);
		System.out.println(methodName + ":iAppoint.iStr = " + iAppoint.iStr);
	}
}

class Appoint {
	int iInt = 1;
	String iStr = "aaa";
}

打印结果:

理解:

1、testChange :iAppoint作为参数在testChange方法中传递的是iAppoint 引用的副本,指向同一地址,对副本值进行改变改变的也就是地址的中的值,iAppoint 指向的是相同地址所以也是改变的

2、testNew:iAppoint作为参数在testChange方法中传递的是iAppoint 引用的副本,指向同一地址, 当引用的副本指向的地址更改后,无论对引用副本值做什么改变,对iAppoint本身指向的地址没有影响

3.3 String 和 StringBuffer

 

Java代码 复制代码 收藏代码
  1. public class StudyString {
  2.  
  3. void printFirst(){
  4. String i="i -- string ";
  5. String i2= new String("i2 -- new string");
  6. StringBuffer ibuf = new StringBuffer("ibuf -- strbuf");
  7. sysout("1 printFirst",i,i2,ibuf);
  8. testChange(i,i2,ibuf);
  9. sysout("3 printFirst",i, i2, ibuf);
  10. testChange2(i, i2, ibuf);
  11. sysout("5 printFirst",i, i2, ibuf);
  12. }
  13. /**
  14. * 分别更改值,查看打印内容
  15. */
  16. private void testChange(String i, String i2, StringBuffer ibufferBuffer) {
  17. i+=" ; 改变值";
  18. i2 += " ; 改变值";
  19. ibufferBuffer.append(" ; 改变值");
  20. sysout("2 testChange",i, i2, ibufferBuffer);
  21.  
  22. }
  23. private void testChange2(String i, String i2, StringBuffer ibufferBuffer) {
  24. String inew = "inew -- new";
  25. i=inew;
  26. String i2new = new String("i2new -- new");
  27. i2=i2new;
  28. StringBuffer iBuffernew = new StringBuffer("iBuf -- new");
  29. ibufferBuffer = iBuffernew;
  30. sysout("4 testChange2",i, i2, ibufferBuffer);
  31. }
  32. /**
  33. * 打印结果
  34. */
  35. private void sysout(String methodStr,String i,String i2,StringBuffer ibufferBuffer) {
  36. System.out.println(methodStr+": i = "+i);
  37. System.out.println(methodStr+": i2 = "+i2);
  38. System.out.println(methodStr+": ibuf = "+ibufferBuffer);
  39. }
  40. public static void main(String[] args) {
  41. new StudyString().printFirst();
  42. }
  43. }  

你可能感兴趣的:(java)