关于Java的传值问题,个人感觉书上说的都不好,请进来听听我的看法。

Java_Design 2008-01-29 02:36:25
关于值传递和引用传递的问题,我想很多人刚开始学的时候都会很迷惑,特别是有些书的文学水平实在不敢恭维。
在此,我特在此对Java的传值和传址提出我自己的一个看法,也许让你能对这个问题的理解起到帮助。
首先:值传递是很好理解的。比如:
public class test {
int a = 3;
public void plus(int b){
b = b+1;
}
public static void main(String args[])
{
test t = new test();
t.plus(t.a);
System.out.println(t.a);
}
}
输出的结果是3.这就是值传递。其实我们可以这样理解:
在plus(int b)函数里,int b是作为这个函数的一个局部变量,在调用这个函数的时候开始位这个变量的内存空间。当我把变量a传给这个函数的时候,实际上是把a变量当时的值拷贝一个放到变量b的分配空间里,b = b+1;这句改变的只是函数的局部变量b的值,当调用结束的时候,变量b的作用范围也就结束了,而你在什么时候修改了变量a的分配空间呢?当然是没有啦(除非你理解成变量a的空间整个放进b的空间里:))

而所谓的引用传递,我觉得这个名次起的很混淆视听。以我自己的理解,一切传递都是拷贝传递。因为对象的标识符代表的是对象的存储地址,所以你把对象的标识符号传递给函数的时候,实际上是把对象地址的拷贝传递给了函数。虽然也是拷贝,但是2个地址拷贝都是指向一个地址的,所以如果在函数里修改了对象,那么也实际上就修改了原先的值。
...全文
533 41 打赏 收藏 转发到动态 举报
写回复
用AI写文章
41 条回复
切换为时间正序
请发表友善的回复…
发表回复
bloodrate 2008-02-01
  • 打赏
  • 举报
回复
我在举个例子

Class a{
int i=123;
}

Class b{
public static void main(String args[])
{
int m=123;
New a();
}
}

你认为我这个例子里的i和m有没有关系,可是我就告诉你i和m指向的内存空间是一样的,因为pool的机制是,为m创建空间存123,在为i创建空间存123之前会把整个pool扫描一遍,如果存在123就指向已经存在的,如果没有,就新建,这个都一样更别说你的b和t了。可惜基础类型没有hashcode要不然费给你打出来看看你才相信。
bloodrate 2008-02-01
  • 打赏
  • 举报
回复
"在调用这个函数的时候开始位这个变量的内存空间。当我把变量a传给这个函数的时候,实际上是把a变量当时的值拷贝一个放到变量b的分配空间里"


哥们你是把C的那套搬过来用,“把a变量当时的值拷贝一个放到变量b的分配空间里”这不是胡扯么,b就是个引用,在C++里面这东西叫“别名”,此时b和t指向的内存空间是一样的,至于值为什么是3,我说的很清楚了,因为3在共享池中存储,共享池采用的是复制替代的原理,用4替代3,此时b指向4,t仍然指向3,函数结束后b消失,4为空引用被gc回收。


学完C在学JAVA不好下手,因为少了指针这个东西虽然感觉容易了,其实有的时候有些人更混淆。
billwindows 2008-02-01
  • 打赏
  • 举报
回复
我来说一下 我的理解 :
引用传递 : 也就是浅拷贝 , 不在堆内存中开辟任何 内存 空间, 只把 盏内存 中的 地址 指向 需要拷贝的对象.
例如 : String a = "aaa" String b = a; b 就是进行了一次浅拷贝,既引用传递, 当然如果改变 a 的值 b 也会跟着改变. 这就是引用传递.

值传递 : 在堆内存中开辟另外一块内存空间 , 拷贝对象的值,而 在盏内存中的地址是不同的.

kyokk2005 2008-02-01
  • 打赏
  • 举报
回复
JF,,,…………
Java_Design 2008-02-01
  • 打赏
  • 举报
回复
csdn真是什么类型的鸟都有!
Java_Design 2008-02-01
  • 打赏
  • 举报
回复
感觉很好笑,实例变量的作用域是所有类的实例成员,你有没有传递参数,何谓传值还是传址?我觉得你真是搞笑,还说我的理解完全错误????
Java_Design 2008-02-01
  • 打赏
  • 举报
回复
楼上的,说了那么多废话。。。。。你写的代码输出当然是4啦,你的变量a是实例变量,又没有参数传递,当然可以直接修改实例变量的内存空间啦。感觉看你说那么多看似深奥的东西,其实你最简单的东西都没理解。
Dan1980 2008-01-31
  • 打赏
  • 举报
回复
JAVA中的引用相当于C/C++中的指针;
而C++中的引用在JAVA中没有对应实现;
所以,严格地说,JAVA中没有引用。
SUN为JAVA所使用的术语“引用”和C++中的引用是两回事。

所以,JAVA的参数传递也就不存在什么引用传递了(因为JAVA根本不支持引用),一切都是值传递。

关于简单类型,很好理解,就是拷贝一个值给被调方法。
这个值一旦拷贝完毕,就和原来的变量脱离一切关系。
所以,如论参数在方法内如何被改变,方法外的变量是永远不变的,因为它们是两个完全无关的变量。

关于对象(即类的实例),传值方式和简单类型精确一致。
但不同的是,被赋予一个对象的变量本身并不包含这个对象,而只是包含该对象的地址。
所以,传值的时候,会把变量的拷贝(即对象地址的拷贝)传给被调方法;这样做的结果是,两个变量指向同一个对象。
在方法内部,虽然你不能改变方法外的那个变量,但因为参数获得了那个变量所指的对象的地址,所以,它可以操作原来变量所指的那个对象。

可以把对象比作电视机,对象引用比作遥控器。
现在我需要让屋子里的另一个人也可以和我一样操作电视机,我会给他一个和我手上一模一样的遥控器,但不是给他一台新的电视机。
于是,两个人都可以同时操作同一台电视机了,这就是地址传递。

但是,如果他把遥控器拿到另一间屋子去操作另一台电视机了,我手上的遥控器不会受丝毫影响,因为,我只是给他一个拷贝,我自己的还是自己的。
所以,这既是地址传递又是值传递。
“地址”是指对象的地址,“值”是指地址的值。这就是JAVA的参数传递。
mayandbrisa_1 2008-01-31
  • 打赏
  • 举报
回复
..
billwindows 2008-01-31
  • 打赏
  • 举报
回复
感觉 还是没有大彻大悟 , 建议你研究下 盏内存 堆内存 对象的深拷贝 浅拷贝 , 用 盏内存和 堆内存 的方式理解这快是最好的 ! 因为比较直观 !
haizhen448 2008-01-31
  • 打赏
  • 举报
回复
Java里面,分两种:
值传递:简单数据类型的传递方式例如 int、float等,变量里存的是值,传递的时候直接传值
引用传递:类的对象,例如String、Object等,变量里存的是地址,地址指向实际的值,传递的时候传的就是地址
bloodrate 2008-01-31
  • 打赏
  • 举报
回复
楼主你的理解是完全错误的

我更改了你的代码,请看:


public class test {
int a = 3;
public void add(){
a=a+1;
}

public void plus(test b){
b.add();
}
public static void main(String args[])
{
test t = new test();
t.plus(t);
System.out.println(t.a);
}
}


输出结果4


下面我要阐述一下为什么你的代码是3而我的代码是4,JAVA存储变量有两种形式:
(1)一种是基础类型(int,long)类型以及自定义类型不用new关键字的(User u;)
(2)另一种是用New的(User U=new User();)
这两种方式有很大的不同,第一种方式存储对象在JVM pool里面,第二种方式存储在JVM Heap里面,你错就错在对JVM pool的运行机理不了解,pool中的数据一旦创建无法人为删除,只能通过gc定期删除,所以int i=5; i=6;新创建6,i指向新的6,但是5依然存在,只不过没有引用指向它了,等待gc将其回收。

楼主吧t.a传给了t.plus();传的是我说的第一类对象,因为在t里面,a=3;定义的,在plus里面,形势参数被指向4(因为3+1)并不是覆盖3的位置,而是新创建一个空间存4,此时形势参数t指向4,外面的实际变量t还指向3相当于函数里外各有一个t分别指向3,4;虽然是把3的地址传进函数去了,但是地址的内容被复制了,所以看起来与传值方式效果相同,JAVA这点好:虽然只保留一种传值方式,还能用这种方式的巧妙变化模拟出另一种方式的效果。

至于我那个例子,就是采用第二种方式,我传的对象在heap里,对heap里的数据更改,就是覆盖原有的位置而不复制,那么自然结果就是4。

在JAVA里根本没有传值这个概念,所有的东西都是引用(内存地址),但是可以通过JAVA特有的复制替代原理用引用模拟实现与传值相同的效果。



asdfcvzxa 2008-01-31
  • 打赏
  • 举报
回复
31 楼,精确
lsydingding 2008-01-31
  • 打赏
  • 举报
回复
基本数据类型都是参数传递,引用数据类型都是值传递,记住没错
gougou8180 2008-01-30
  • 打赏
  • 举报
回复
全部是传引用,相当于是指针吧
dracula_zby 2008-01-29
  • 打赏
  • 举报
回复
JAVA里面的传引用不就是和C里面的传地址是类似的么?
zhuxueke_830111 2008-01-29
  • 打赏
  • 举报
回复
呵呵~编程思想里这一部分也着重讲了,你说的和书上的一样~我赞同
mdzlkj 2008-01-29
  • 打赏
  • 举报
回复
传值就相当于你把你的文件拷贝到另一个地方,你对你所拷贝的文件(和源文件有一模一样的信息)做什么都不会影响源文件
传引用就相当于你把该文件创建个快捷方式(差不多),你打开了,修改了,也就修改了
个人理解就这样
KingNE 2008-01-29
  • 打赏
  • 举报
回复
牛B
mcluvin 2008-01-29
  • 打赏
  • 举报
回复
java语言里只有传值,没有传引用。

语义上很容易混淆,Java里引用类型传值过去的就是引用,但是跟传引用的“引用”语义还是有区别的。

Java里传过去的值是不会改变的,能改变的只是其引用的对象。但其他语言中所谓的传引用是能改变该引用的。

说了一堆,呵呵
加载更多回复(21)
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧