这几天重构项目代码遇到一个疑问:可不可以在方法A中定义一个boolean变量b为false,然后A调用方法C把b传递到C方法中经过一些列业务判断后修改为true,C执行结束后A方法中b的值还是原来的false而并不会取到C方法修改后的true(当然实际业务并不是这样写,只是有这个疑问)。

查了一下资料,结论是这关系到Java方法传递参数是传值还是传址,方法执行的时候会不会拷贝副本再使用的问题。

回答是 ①Java方法传递传值不传址;②参数传递到方法之后会先进行一份拷贝,方法中使用的是参数的拷贝而参数本身。

示例代码如下:

import domain.User;

/**
* @author cc
* java 方法执行时传参数是传值,然后拷贝一个副本,方法中修改的是拷贝的副本,并不是值本身
*
* 当参数是引用类型时,传的值是引用的值,不是对象的值。拷贝一份引用的副本,副本的值和原来的值相等
* 也就是说副本指向的对象和原值指向的是同一个对象
*/
public class PassValueTest
{ public static void main(String[] args)
{
PassValueTest p = new PassValueTest();
final int i = 1;
boolean b = true; System.out.println("===测试int类型参数会拷贝副本后使用" );
System.out.println("原来i=" + i);
p.changeI(i);
System.out.println("在调用changeI之后 i = " + i);//i的值没有被改变
System.out.println(); System.out.println("===测试boolean类型参数会拷贝副本后使用" );
System.out.println("原来b=" +b);
p.changeB(b);
System.out.println("在调用changeB之后b = " + b);
System.out.println(); System.out.println("===测试引用类型参数传递的是引用的值并拷贝副本后使用 ");
User user = new User("dd", 28);
p.changeUser(user);
System.out.println("在调用ChangeUser方法之后user:" + user);
System.out.println(); System.out.println("===测试引用类型参数传到方法里面后是否会被先拷贝副本");
User userA = new User("userA", 10);
User userB = new User("userB", 12); p.changeCopy(userA, userB); System.out.println("在调用changeCopy方法之后,实际上userA和userB并没有改变:userA: " + userA
+",userB:" + userB);//实际上userA 和userB的引用并没有被改变
System.out.println("如果在方法中没有拷贝参数而直接使用参数的话,userA和userB的引用应该会像在方法中被调换的");
}
public int changeI(int i)
{
i = i+2;
System.out.println("在changeI方法中修改后i副本= " + i);
return i;
}
public boolean changeB(boolean b)
{
b = false;
System.out.println("在changeB方法中修改后b副本= " + b);
return b;
} public void changeUser(User user)
{
System.out.println("在changeUser方法中,user参数副本指向的对象和user参数指向的对象是同一个对象,修改前user:" + user);
user.setName("cici");
user.setAge(18);
System.out.println("在changeUser方法中,修改了参数副本所指向对象的值,修改后user:" + user);
} public void changeCopy(User userA,User userB)
{
System.out.println("在方法changeCopy中UserA和UserB的引用副本在修改前是 ,userA副本 :"
+ userA +", userB副本 : " + userB);
User temp = userA;//把A引用副本赋值给temp,就是说temp引用指向A对象
userA = userB;//把B引用副本赋值给A引用副本,就是说此时A引用副本指向B对象
userB = temp;//把temp引用赋值给B引用副本,就是说此时B引用副本指向A对象 System.out.println("在方法changeCopy中UserA和UserB的引用副本已经被调换 ,userA副本 :"
+ userA +", userB副本 : " + userB);
}
}

用到的User类:

 package domain;

 public class User {
private String name;
private int age; public User(String name,int age) {
this.name = name;
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} @Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("[").append(name).append(", age=").append(age)
.append("]");
return builder.toString();
} }

运行结果:

Java方法传递参数传值还是传址的问题的更多相关文章

  1. 一段代码让你秒懂java方法究竟是传值还是传地址

    先看看代码以及执行结果: 凝视写得非常清楚了.我就不多说了. 我说说我的结论.事实上在java中没有传值还是传址的概念,java仅仅有引用的概念.引用类似传址.只是是一个变量名中保存着对象的地址,地址 ...

  2. JAVA方法传递参数:传值?传引用?

    先来看下面这三段代码: //Example1: public class Example1 { static void check(int a) { a++; } public static void ...

  3. Python 传值和传址 copy/deepcopy

    传值:被调函数局部变量改变不会影响主调函数局部变量 传址:被调函数局部变量改变会影响主调函数局部变量 Python参数传递方式:传递对象引用(传值和传址的混合方式),如果是数字,字符串,元组则传值:如 ...

  4. java方法中,传参是传值还是传址问题(对比C语言、C#和C++)

    问题引出: 编写一个简单的交换值的小程序,如果我们只是简单地定义一个交换函数接收两个数,在函数内部定义一个中间变量完成交换.那么当我们把a,b两个实参传给这个函数时,往往得不到预期的结果.这是为什么呢 ...

  5. Java传值和传址

    调用函数时,传的参数过去可能是传值,也可能是传址.如果是传值,函数内部的操作对参数的值没有影响:如果是传址,函数内部的操作是对参数指向的内存进行操作,会影响参数的值. Java到底是传值还是传址?用下 ...

  6. javascript的变量,传值和传址,参数之间关系

    先把收获晾一下: 1.javascrip变量包含两种类型的值,一种为引用类型的值,一种是基本类型的值.引用类型包括:Array,Object,Function(可以这么理解,非基本类型的都是引用类型) ...

  7. Java方法的参数传递方式为: 值传递

    Java方法的参数传递方式为: 值传递 对于基本数据类型作为参数传递时, 是"按值传递", 这点都认识很清楚. 但是, 当对象或者说引用作为参数传递, Java 的参数传递方式是& ...

  8. JAVA传值与传址

    要了解JAVA中的传值与传址问题,必要先要了解JVA中的栈内存和堆内存,>>>>点些查看<<<<昨天写的学习记录 栈:基本数据类型.数据的引用变量,这两 ...

  9. javascript . 05 json的组成、for...in 遍历对象、简单数据类型与复杂数据类型的传值与传址、内置对象

    对象字面量  JSON var obj = { aaa :999}; var json={"aaa":999,"bbb":888}; "kay&quo ...

随机推荐

  1. bzoj 2565: 最长双回文串【manacher+线段树】

    因为我很愚蠢所以用了很愚蠢的O(nlogn)的manacher+线段树做法 就是开两个线段树mn和mx分别表示左端点在i的最长回文子串和右端点在i的最长回文子串 用manacher求出每个点的最长回文 ...

  2. P5169 xtq的异或和(FWT+线性基)

    传送门 我咋感觉我学啥都是白学-- 首先可以参考一下这一题,从中我们可以知道只要知道两点间任意一条路径以及整个图里所有环的线性基,就可以得知这两个点之间的所有路径的异或和 然而我好像并不会求线性基能张 ...

  3. 2017.11.7~8模拟测试总结---暨NOIP2017考前对策

    最后两天了,第三天就是NOIP2017--Day1了. 刚刚考完了这个学期从开学以来的最后一场模拟赛了.首先要对于这场模拟赛做一次深刻的反思. 考完才猛地惊叹这是最后一场模拟赛了,然而题目并不难,也保 ...

  4. mysql 如何创建一个简单的存储过程

    1 用mysql客户端登入2 选择数据库 mysql>use test3 查询当前数据库有哪些存储过程 mysql>show procedure status where Db='test ...

  5. Thymeleaf 总结

    在javaScript中使用表达式 var list = /*[[${list}]]*/ null;   <script th:inline="javascript"> ...

  6. AJPFX谈Java 性能优化之基本类型 vs 引用类型

    ★名词定义 先明确一下什么是“基本类型”,什么是“引用类型”. 简单地说,所谓基本类型就是 Java 语言中如下的8种内置类型: booleancharbyteshortintlongfloatdou ...

  7. 04.Java多线程并发库API使用3

    1.java5的Semaphere同步工具 Semaphore可以维护当前访问自身的线程个数,并提供了同步机制.使用Semaphore可以控制同时访问资源的线程个数,例如,实现一个文件允许的并发访问数 ...

  8. elasticsearch 2.4.0安装说明

    首先从官网下载安装包,是个压缩文件,然后解压 在es目录下找到es的配置文件 修改集群(cluster)名称 PS:一般情况下一台机只部署一个es程序,也就是一个集群,默认集群名是ewater_mai ...

  9. ag-grid-vue的 行默认选中

    that.$nextTick(() => { that.gridListOptions.api.onGroupExpandedOrCollapsed(); that.$nextTick(() = ...

  10. BottomNavigationBar底部导航条用法

    先来张效果图 接下来是实现过程 1.加入依赖 compile 'com.ashokvarma.android:bottom-navigation-bar:1.3.0' 2.xml布局 fragment ...