java学习——java按值传递和按址传递

java中的按值传递和按址传递(按引用传递),要明白这两个概念,要理解按值和按址。

大家好,又见面了,我是全栈君。

看这篇也可以看一下最新整理的文:

Java内存管理-Stackoverflow问答-Java是传值还是传引用?(十一)

先复制一个面试/笔试的题:

当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

答案:

是值传递。Java语言的方法调用只支持参数的值传递。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的属性可以在被调用过程中被改变,但对对象引用的改变是不会影响到调用者的。C++和C#中可以通过传引用或传输出参数来改变传入的参数的值,但是在Java中却做不到。

java中的按值传递和按址传递(按引用传递),要明白这两个概念,要理解按值和按址。
下面举个简单的例子来说明:
比如你去国外旅行,拍了一张特别好的照片,你想分享给你的朋友,那么有两种方式,第一种是你直接将这个照片发送给你的朋友,也就是给你朋友这个照片的副本;第二种是假如你将这张及其好的照片上传到一个QQ(微博)等,你将会得到一个访问这个照片的地址(Url),此时在将这个url分享给你的朋友。
如上例子,第一种可以认为是按值传递,第二种可以认为是按址传递(按引用传递)。知道了这个概念。在进行下面的简单分析。

  • 按值传递:只有当参数为基本类型变量的时候,java按这种策略的方式传递。
    上面的分享照片,你的朋友拿到的照片是你的副本,那么朋友对照片的修改不会影响你的照片,你对照片的修改也不会影响到你给朋友分享的照片。

  • 按址传递:只有当参数为引用类型变量,java按这种策略方式进行传递。
    上面的Url地址给朋友,那么如果朋友也有修改的权限,朋友对照片进行操作,自己访问的照片就是朋友操作结果后的结果。

下面通过代码来解释这个例子:

package com.dufy.reforvalue;

import java.util.Arrays;

/**
 * java中 按值传递和按址传递
 * 按值传递:基本类型变量-按值传递,按值传递通过复制获取参数的副本
 * 按址传递:引用类型变量-按址传递,按址传递通过传递对象的引用地址
 * 
 * @author dufy
 * @creation 2017年2月9日
 */
public class ReferenceOrValue {

	/**
	 * 基本类型,按值传递
	 * 举例:给朋友分享你的照片,对方接收的是你的照片的一个实际的副本,
	 * 你和朋友分别对各自的照片进行操作,不会影响彼此的照片!
	 */
	public static void testVal(int photo){
		photo++;//朋友对照片进行修改
		System.out.println("My friend see photo = " + photo);
	}
	
	/**
	 * 引用类型:按址传递
	 * 举例:给朋友分享你的照片,分享的是你上传网上的一个照片的Url(地址),
	 * 你和朋友都可以通过这个地址访问照片,并对照片进行一个操作!
	 */
	public static void testRef(Photo photo){
		photo.setPhoto("java Photo,Great!");//朋友对你的照片进行修改
		System.out.println("My friend see photo = " + photo.getPhoto());
	}
	
	/**
	 * 引用类型:按址传递
	 * 因为数组是一个引用类型。所以传递进去的是它们的引用,故在方法中互换了它们的值,也必然影响到它们原来的值.
	 */
	public static void testArrayRef(int[] array){
		for (int i = 0; i < array.length; i++) {
			array[i] = 0;
		}
		System.out.println("testArrayRef array is = "+Arrays.toString(array));
	}
	public static void main(String[] args) {
		//一:按值传递
		int photo = 10;//定义要发送的照片
		testVal(photo);//将照片发发送你朋友,朋友得到的是一个副本
		System.out.println("My see photo = " + photo);
		
		
		//二:按址传递
		Photo p = new Photo();//定义一个照片的对象,我自己拍摄的java photo
		p.setPhoto("java photo");
		
		testRef(p);//将照片对象(即 Url地址) 发送你朋友,朋友得打的是一个Url(地址),Url打开才是照片
		System.out.println("My friend see photo = " + p.getPhoto());
		
		//三:数组也是对象,数组在堆内存。引用是在栈。
		int array[] = {1,2,3,4,5};
		testArrayRef(array);
		System.out.println("array is = "+Arrays.toString(array));
		
	}
	
	/**
	 * 照片类
	 */
	static class Photo{
		String photo;

		public String getPhoto() {
			return photo;
		}

		public void setPhoto(String photo) {
			this.photo = photo;
		}
		
	}
}

输出的结果如下:

My friend see photo = 11
My see photo = 10
My friend see photo = java Photo,Great!
My friend see photo = java Photo,Great!
testArrayRef array is = [0, 0, 0, 0, 0]
array is = [0, 0, 0, 0, 0]

小插曲:有下下面这一道题:这个method应该怎么写呢?

public static void main(String[] args) {
		int a = 10;
		int b = 20;
		method(a,b);//需要在method被调用后,仅打印出a=100,b=200,请写出method(a,b)方法!
		System.out.println("a = " + a);
		System.out.println("b = " + b);
	}

肯定有很多人和我之前一样,想都没想就写出下面的代码:

private static void method(int a, int b) {
		a*=10;
		b*=10;
	}

但是运行结果后你会发现,没有打印出理想的结果!

这时候如果你仔细看来了上面的介绍就不难理解为什么会出现这样的结果了!

给出这道题可能正确的结果:

private static void method(int a, int b) {
		System.out.println("a=100,b=200");
		System.exit(0);
	}

附:

public static void main(String[] args) {
		int a = 10;
		int b = 20;
		method(a,b);//需要在method被调用后,仅打印出a=100,b=200,请写出method(a,b)方法!
		System.out.println("a = " + a);
		System.out.println("b = " + b);
		System.out.println("a = " + Integer.valueOf(a));
		System.out.println("b = " + Integer.valueOf(b));
	}

	private static void method(Integer a, Integer b)  {
		try {
			Field filea = a.getClass().getDeclaredField("value");
			filea.setAccessible(true);
			filea.setInt(a, 100);
			Field fileb = b.getClass().getDeclaredField("value");
			fileb.setAccessible(true);
			fileb.setInt(b, 200);
			
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	private static void method1(int a, int b) {
		System.out.println("a=100,b=200");
		System.exit(0);
	}

输出结果:

a = 10
b = 20
a = 100
b = 200

你觉得正确的答案是什么,可以给我留言和评论,欢迎讨论!

java到底是值传递还是引用传递? 知乎:https://www.zhihu.com/question/31203609
你会swap吗,按值传递还是按引用?:http://www.cnblogs.com/foreach-break/p/call-by-reference-OR-call-by-value.html

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

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/121191.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 数学速算法_小学初中高中 数学奥数教材及习题讲解(共42册PDF)「建议收藏」

    数学速算法_小学初中高中 数学奥数教材及习题讲解(共42册PDF)「建议收藏」学习勤育儿|爱自己在育儿的道路上,家长和孩子一同成长;慢慢陪孩子走,把我们的时间浪费在孩子身上,是世间最有价值的浪费!资源介绍奥数对青少年的脑力锻炼有着一定的作用,可以通过奥数对思维和逻辑进行锻炼,对学生起到的并不仅仅是数学方面的作用,通常比普通数学要深奥些。奥数相对比较深,数学奥林匹克活动的蓬勃发展,极大地激发了广大少年儿童学习数学的兴趣,成为引导少年积极向上,主动探索…

  • CANalyzer及CANOE使用五:无DBC,调CSV方式的网关信号转发或单通道信号值控制ECU其他信号变化(包含设计自动化测试)[通俗易懂]

    CANalyzer及CANOE使用五:无DBC,调CSV方式的网关信号转发或单通道信号值控制ECU其他信号变化(包含设计自动化测试)[通俗易懂]前言Panel界面CSV文件解析发送与接收————————————————前言同事:CAN网络UDS、NM等可以实现自动化,功能信号是否也可以?有简单方法吗?手动测太累了,矩阵表信号那么多,几十个Bit都够算了,脑袋都昏了。我:可以哇,那就整一个自动算信号bit值的吧。同事:不仅要算,还要判断ECU接收某些开关信号、温度、档位等的一系列反应(其他信号值的改变是否正确)我:可以,整一个同事:还有可能有网关转发信号起始bit,bit长度,接收的一方的信号值也要变。我:。。。。。。Pa.

  • Fragment onResume不执行「建议收藏」

    Fragment onResume不执行「建议收藏」本博客解决的主要问题:在多个fragment切换的时候刷新各自的fragment,一般我们会优先想到onResume(),但是有时不起作用。解决办法:我们可以重写setUserVisibleHint()@OverridepublicvoidsetUserVisibleHint(booleanisVisibleToUser){super.setUserVis

  • android之按钮单击事件及监听器的实现方式

    第一种,匿名内部类作为事件监听类. Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { System.out.println(

  • ES数据库操作入门总结「建议收藏」

    ES数据库操作入门总结「建议收藏」elasticsearch总的来说应该算是一个搜索引擎,公司使用一般是作为日志结果查询。json文档格式,倒排索引的快速以及分布式的特性,使得es可以在大量数据中快速查询到结果。windows安装和配置可参考官方网址。https://www.elastic.co/guide/en/elasticsearch/reference/current/zip-windows.html倒排查询可参考这个知乎回答https://zhuanlan.zhihu.com/p/62892586可以使用浏览器的U

  • cocos android分析

    cocos android分析

发表回复

您的电子邮箱地址不会被公开。

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