finemi 2015-06-10 13:31 采纳率: 100%
浏览 5549
已采纳

java中String究竟是传递的值,还是引用

很多人说,java中的String虽然是对象,但是具有值类型的特征。他是值传递,传递的值。
我认为这这种说法完全是错误的。
String和普通对象毫无区别,和其他对象一样,传递的是引用,而不是值。
一段String的运用代码:

 String a = "123";
public void change(String a){
    a = "234";
}

很多人会说,a的值没有变,是因为String是值传递,问题是,就算对于一个普通对象,这样的用法,该对象的值也是不会改变的!这是一个大大的误区。java中根本没有真正的引用传递,不想C#中有ref关键字!
比如:

 Person p = new Person("张三");
public void change(Person p){
    p = new Person("李四");
}

上面对于String的使用和这个自定义Person类的使用上,根本没有本质上的区别。同样,外面的p变量依然是”张三”,不会是“李四。”

同样的代码,放入C#中,加上ref关键字:

 Person p = new Person("张三");
public void Change(ref Person p){
    p = new Person("李四");
}

结果是,p变为了“张三”!

所以说,个人认为java中的String并没有什么特殊性,和其他类一样,同样保存的对象的引用,传递的引用。唯一的特殊性,就是可以直接用“”双引号的方式创建字符串对象。

  • 写回答

12条回答 默认 最新

  • *长铗归来* 2015-06-11 08:35
    关注

    java 传参都是传的值,这点就现在的java而言毫无疑问。
    但是java的变量在方法中一般来说有2种类型:基本类型与对象(通常这个对象是引用类型),基本类型保存在栈区,对象保存在堆区

    至于C# 的public void Change(ref Person p)或者c++的public void Change(Person& p)就语法角度来讲,确实是引用。虽然没有研究,但是觉得,这只是语法糖而已。因为无论c#或者C++的程序调用,都是基于栈机制的,所以在函数调用时,都是有明确的参数值入栈的,这时的引用参数应该是传的地址,所有的引用类型变量在编译时都由编译器改成了指针类型的操作。所以说引用是语法糖。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
  • 一杯苦茶 2015-06-10 13:51
    关注

    赞同,我认为你的理解是对的

    评论
  • danielinbiti 2015-06-10 14:08
    关注
     首先,“java中的String虽然是对象,但是具有值类型的特征。他是值传递,传递的值”这句话是对的
     其次,String a = "123";不创建对象,只有常量和变量
    
    
    评论
  • 强圆nice 2015-06-10 14:12
    关注

    在Java中过多考虑引用(指针)和值之间的关系是步入歧途,这正是Java的设计者极力避免你考虑的问题。
    你需要明白的是:
    1、Java中所有方法的参数的传递都是“值传递”;
    2、Java中所有对象类型的变量的“值”,本质上说,包含了Java堆中的实际对象的地址,你可以大体认为Java的变量对应了C/C++中的指针(其实这里面有更复杂的机制)。事实上,Java并不像C/C++一样明确的区分“值语义”与“引用语义”,Java栈中也不会存放任何对象的实体(这点与C/C++不同,C/C++栈中可以存放对象实体),所有的Java对象都是在堆中。

    概念上的区别在于,我这里提到的“变量”是指Java栈中的内容,对应你说的“引用”;我提到的“对象”是指Java堆中的实体,对应你说的“值”。而一般Java教材中提到的“值传递”,是指这些“变量”的内容的传递,不是Java堆中的对象实体的传递。

    你用字符串来做实验,并推广为所有Java对象的做法,并不是特别合适。Java的String类型有特殊的处理:所有编译期认识的字符串,都会被放到常量池,于是下面的语句:
    a = "s";
    b = "s";
    a和b并不像其它对象一样有创建的动作,都是直接指向常量池中的"s",所以你可以得到a==b。而下面的语句:
    a = new String("s");
    b = new String("s");
    是分别在Java堆中创建了2个对象,此时a!=b。

    本质上说,对于基本数据类型(整数、字符等),Java的符号==,用于判断二者的值是否相等;对于对象类型,Java的符号==,用于判断两个变量是否是“同一个对象”,equals()方法才是用于判断两个对象是否相等。

    你希望实现的swap逻辑,在Java中通常认为是无法实现的。拿你这个例子来说,swapValue()中的tmpValue无论怎么更改,只是改变tmpValue自己的内容(即不断指向不同的对象),并不会改变value中的内容(始终指向同一个对象)。这也是为什么Java最初说自己永远是值传递。你只有改变tmpValue指向的对象的值(通过调用这个对象的方法或是更改它的属性),使用value访问时,才能看到这些改变。

    为了弥补这个缺陷,C#才加入了ref关键字,允许传入变量的引用(如果参考C/C++,C#传递的实际是二级指针,它的内容是栈中的变量的地址)。

    评论
  • 青春唱不完的歌 2015-06-10 14:27
    关注

    java都是值传递,没有引用

    评论
  • Linda_Lindaaaa 2015-06-10 14:46
    关注

    String是引用类型,和其他引用类型不同的是它可以直接用“”赋初值,而不用new来创建对象,赋值后在相当于是常量。值不能改变。

    评论
  • 15004600279 2015-06-10 15:05
    关注

    String和Integer Long Boolean Short Byte Char Dobule是经过特殊处理的,不信你自己定义个类试下你刚才这种方法就好了.

    评论
  • frank_20080215 2015-06-11 00:04
    关注

    是对象的引用。string就是对象

    评论
  • edouardzyc 2015-06-11 01:30
    关注

    你如果不是p = new Person("李四");
    而是p.name = "李四"的话, 外面的对象也会变成李四的

    评论
  • Young_Liu 2015-06-11 01:51
    关注

    绝对是引用 只是java里弱化了这点

    评论
  • xingjiarong 2015-06-11 02:44
    关注

    这个跟java的字符串缓冲池有关,可以参考一下我的博客

    评论
  • 勿忘心安seq 2016-10-15 12:39
    关注

    都别争了,String类是final的,即指针常量,指向不可变。

    评论
查看更多回答(11条)

报告相同问题?

悬赏问题

  • ¥15 java为什么这个按钮监听事件不触发
  • ¥20 unity打光没有照亮物体
  • ¥25 powershell如何拷贝1周前的文件
  • ¥15 询问MYSQL查询SQLSERVER数据表并比较差异后,更新MYSQL的数据表
  • ¥15 关于#前端#的问题,请各位专家解答!
  • ¥15 最小生成树问题 Prim算法和Kruskal算法
  • ¥25 医院住院病人呼叫器设计
  • ¥15 不想和现在的团队合作了,怎么避免他们对程序动手脚
  • ¥20 C语言字符串不区分大小写字典排序相关问题
  • ¥15 关于#python#的问题:我希望通过逆向技术爬取1688搜索页下滑加载的数据