f*******b 发帖数: 520 | 1 最近刚开始练习用java做题,突然发现其没有pass parameters by reference,比如C#
里的 ref 功能
比如
Object o = "Hello";
mutate(o);
System.out.println(o);
private void mutate(Object o)
{
o = "Goodbye";
}
结果是显示"Hello",怎样让其显示"Goodbye"呀? |
c******o 发帖数: 534 | |
f*******b 发帖数: 520 | 3
我看到的是不管什么java都是pass by value, 所以当我pass "GoodBye"时只是改变了
parameter的值,没能触动到之前定义的reference :(
【在 c******o 的大作中提到】 : 听说java里面都是reference啊
|
g*********e 发帖数: 14401 | 4
【在 c******o 的大作中提到】 : 听说java里面都是reference啊
|
v*****d 发帖数: 348 | 5 java 是pass by value, 不过value是一个reference的值。o = "Goodbye"把一个新的
reference给了o, 当然不会生效。
至于怎么显示"Goodbye", String本身就是immutable的, 无解,除非你搞个
StringBuilder.
【在 f*******b 的大作中提到】 : : 我看到的是不管什么java都是pass by value, 所以当我pass "GoodBye"时只是改变了 : parameter的值,没能触动到之前定义的reference :(
|
g**G 发帖数: 767 | 6 你一开始声明了一个string hello, 然后声明了o,这个o是一个object的引用,这个引
用指向hello这个string
然后调用mutate,传进去的其实是o这个引用地址的一个copy
你无论在nutate里如何操作这个引用地址,函数外的o的引用还是不会变,始终指向
hello
你没法通过函数改这个
因为string是immutable的
如果o指向的不是string是一个你自定义的类
那么你在mutate里改o本身的内容,是可以反映出来的 |
s*******n 发帖数: 305 | 7 楼上正解!!!
用数组就能试出来, 输出结果为2.
int[] x = {0};
testRef(x);
System.out.println(x[0]);
public static void testRef(int[] y){
y[0] = 2;
} |
f*********g 发帖数: 110 | 8 请问各位,反转链表,用recursion来写,java 应该如何写?我一直觉得应该新建一个
类来wrap node 才能做到,比如下面,一直觉得这种方法不是很clean, 请问有更好的
方法吗? 不用新建类的
class WrapperNode{
ListNode node;
} |
D****6 发帖数: 278 | |
f*******b 发帖数: 520 | 10 多谢大牛,
刚试了不仅是String,如果是int也不行。但是像你说的一样自定义的类是可以改动的。
只有数组或是自定义的类,在指向的他们的值的时候改他们的值,才可以改动。如果只
是在函数里单纯的赋值是不奏效的。 |
|
|
g**G 发帖数: 767 | 11 Why do you want to use recursion..?
public ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
ListNode next = null;
while (curr.next != null) {
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
curr.next = prev;
return curr;
}
【在 f*********g 的大作中提到】 : 请问各位,反转链表,用recursion来写,java 应该如何写?我一直觉得应该新建一个 : 类来wrap node 才能做到,比如下面,一直觉得这种方法不是很clean, 请问有更好的 : 方法吗? 不用新建类的 : class WrapperNode{ : ListNode node; : }
|
g**G 发帖数: 767 | 12 String and int/long/char ... are different.
String is immutable, int/long/char/short ... are primitive types.
的。
【在 f*******b 的大作中提到】 : 多谢大牛, : 刚试了不仅是String,如果是int也不行。但是像你说的一样自定义的类是可以改动的。 : 只有数组或是自定义的类,在指向的他们的值的时候改他们的值,才可以改动。如果只 : 是在函数里单纯的赋值是不奏效的。
|
s**********r 发帖数: 8153 | |
s*******n 发帖数: 305 | 14
弱弱的问下,ListNode随意定义吗?
【在 g**G 的大作中提到】 : Why do you want to use recursion..? : public ListNode reverseList(ListNode head) { : ListNode prev = null; : ListNode curr = head; : ListNode next = null; : while (curr.next != null) { : next = curr.next; : curr.next = prev; : prev = curr; : curr = next;
|
f*********g 发帖数: 110 | 15 能详细解释一下吗?谢谢啦
【在 D****6 的大作中提到】 : 弄个dummyhead就好了。
|
f*********g 发帖数: 110 | 16 面试官问的阿,我也没有办法啊,哎,找个工作真辛苦
【在 g**G 的大作中提到】 : Why do you want to use recursion..? : public ListNode reverseList(ListNode head) { : ListNode prev = null; : ListNode curr = head; : ListNode next = null; : while (curr.next != null) { : next = curr.next; : curr.next = prev; : prev = curr; : curr = next;
|
z****e 发帖数: 54598 | 17 string是immutable滴
listnode用递归做个反转是基本功,是个常见的面试题
很多金融公司比如银行喜欢问,java版有人说过这个问题
if(head==null) return null;
if(head.next == null) return head;
ListNode second = head.next;
ListNode current = head;
current.next = null;
head = recursive(second);
second.next = current;
return head; |
D****6 发帖数: 278 | 18 其实就是用listnode自己当个wrapper.
ListNode newHead = new ListNode(-1);
public ListNode reverse(ListNode head, ListNode newHead) {
if(head.next == null) { // you are at the tail
newHead.next = head;
return head;
}
......
}
外面return newHead.next; |
f*********g 发帖数: 110 | 19 这个方法很聪明啊,多谢。
【在 D****6 的大作中提到】 : 其实就是用listnode自己当个wrapper. : ListNode newHead = new ListNode(-1); : public ListNode reverse(ListNode head, ListNode newHead) { : if(head.next == null) { // you are at the tail : newHead.next = head; : return head; : } : ...... : } : 外面return newHead.next;
|
f*********g 发帖数: 110 | 20 你的这个方法不错,避免了内部修改head, 这是我的代码,大牛觉得呢?
ListNode rev(ListNode head){
if(head==null||head.next==null) return head;
WrapperNode newhead = new WrapperNode();
reversehelp(head, newhead);
return newhead.node;
}
ListNode reversehelp(ListNode head, WrapperNode newhead){
if(head.next==null){
newhead.node=head;
return head;
}
ListNode cur=reversehelp(head.next,newhead);
cur.next=head;
head.next=null;
return head;
}
class WrapperNode{
ListNode node;
}
【在 z****e 的大作中提到】 : string是immutable滴 : listnode用递归做个反转是基本功,是个常见的面试题 : 很多金融公司比如银行喜欢问,java版有人说过这个问题 : if(head==null) return null; : if(head.next == null) return head; : ListNode second = head.next; : ListNode current = head; : current.next = null; : head = recursive(second); : second.next = current;
|
|
|
z****e 发帖数: 54598 | 21 前面添加一个头node的话叫做safe guard
看你顺手不顺手,如果顺手的话,尽管加
都是工具,你觉得哪个顺手就操哪个上
【在 f*********g 的大作中提到】 : 你的这个方法不错,避免了内部修改head, 这是我的代码,大牛觉得呢? : ListNode rev(ListNode head){ : if(head==null||head.next==null) return head; : WrapperNode newhead = new WrapperNode(); : reversehelp(head, newhead); : return newhead.node; : : } : : ListNode reversehelp(ListNode head, WrapperNode newhead){
|
h**6 发帖数: 4160 | 22 把楼主的代码翻译成c++了,输出为Hello。
#include
void mutate(const char *o)
{
o = "Goodbye";
}
int main ()
{
const char *o = "Hello";
mutate(o);
printf("%s\n", o);
return 0;
}
如果mutate函数定义为void mutate(const char *&o),则输出为Goodbye。 |
f*******b 发帖数: 520 | 23
大牛转的太棒了,关键是C++有&可以用,c#有 ref 和 out, JAVA的话就麻烦许多,有
没有什么简便的方法替代&的?
【在 h**6 的大作中提到】 : 把楼主的代码翻译成c++了,输出为Hello。 : #include : void mutate(const char *o) : { : o = "Goodbye"; : } : int main () : { : const char *o = "Hello"; : mutate(o);
|
z****e 发帖数: 54598 | 24 java的内存管理是交给jvm去做的
如果你想操作内存地址的话,那还是回去用c
【在 f*******b 的大作中提到】 : : 大牛转的太棒了,关键是C++有&可以用,c#有 ref 和 out, JAVA的话就麻烦许多,有 : 没有什么简便的方法替代&的?
|
x*****p 发帖数: 1707 | 25 Java is definitely pass by reference. However, String is immutable, that is
why you can not change its value by reference. If you want to output "
Goodbye", you can use reflection. The code is below.
private void mutate(Object str) {
try {
Field field = String.class.getDeclaredField("value");
field.setAccessible(true);
char[] newValue = "Goodbye".toCharArray();
field.set(str, newValue);
Field field2 = String.class.getDeclaredField("count");
field2.setAccessible(true);
field2.set(str, newValue.length);
} catch (Exception e) {
e.printStackTrace();
}
}
C#
【在 f*******b 的大作中提到】 : 最近刚开始练习用java做题,突然发现其没有pass parameters by reference,比如C# : 里的 ref 功能 : 比如 : Object o = "Hello"; : mutate(o); : System.out.println(o); : private void mutate(Object o) : { : o = "Goodbye"; : }
|
x*****p 发帖数: 1707 | 26 The above example proves that Java is pass by reference. |
w**z 发帖数: 8232 | 27 Java makes a copy of the object reference ,and pass that by value .
【在 x*****p 的大作中提到】 : The above example proves that Java is pass by reference.
|
x*****p 发帖数: 1707 | 28 其实这就是对Reference和Value的定义的歧义。Reference指的就是一个Object的地址
,当然也是一个值。可Value一般指的是这个地址的内存中所对应的内容。
举个例子。有一个十六进制的地址1A2B3C4D,这个地址对应的内存空间存了一个数是
100。那么,我们称的Reference,指的就是这个地址1A2B3C4D的值,而Value指的就是
100这个值。
许多教科书,把地址1A2B3C4D这个值称为Value,我以为是不妥的。如果这样,那100这
个值称什么呢?
【在 w**z 的大作中提到】 : Java makes a copy of the object reference ,and pass that by value .
|
w**z 发帖数: 8232 | 29 你愿怎么叫都无所谓,只要明白到底发生什么就行了。
【在 x*****p 的大作中提到】 : 其实这就是对Reference和Value的定义的歧义。Reference指的就是一个Object的地址 : ,当然也是一个值。可Value一般指的是这个地址的内存中所对应的内容。 : 举个例子。有一个十六进制的地址1A2B3C4D,这个地址对应的内存空间存了一个数是 : 100。那么,我们称的Reference,指的就是这个地址1A2B3C4D的值,而Value指的就是 : 100这个值。 : 许多教科书,把地址1A2B3C4D这个值称为Value,我以为是不妥的。如果这样,那100这 : 个值称什么呢?
|
w**z 发帖数: 8232 | 30 Java passes the value 1A2B3C4D itself when calling method. that is how it is
called pass by value. it does make a copy of that and pass it.
【在 x*****p 的大作中提到】 : 其实这就是对Reference和Value的定义的歧义。Reference指的就是一个Object的地址 : ,当然也是一个值。可Value一般指的是这个地址的内存中所对应的内容。 : 举个例子。有一个十六进制的地址1A2B3C4D,这个地址对应的内存空间存了一个数是 : 100。那么,我们称的Reference,指的就是这个地址1A2B3C4D的值,而Value指的就是 : 100这个值。 : 许多教科书,把地址1A2B3C4D这个值称为Value,我以为是不妥的。如果这样,那100这 : 个值称什么呢?
|
|
|
P***k 发帖数: 39 | 31 记得好像是thinking in java写过,java所有都视为pass by value.没有pass by
reference. |
r********r 发帖数: 208 | 32 "1A2B3C4D" is the value of the reference. Therefore, this is "pass by value"
;
"pass by reference" means "pass the address of the reference", and the
reference's value is 1A2B3C4D.
【在 x*****p 的大作中提到】 : 其实这就是对Reference和Value的定义的歧义。Reference指的就是一个Object的地址 : ,当然也是一个值。可Value一般指的是这个地址的内存中所对应的内容。 : 举个例子。有一个十六进制的地址1A2B3C4D,这个地址对应的内存空间存了一个数是 : 100。那么,我们称的Reference,指的就是这个地址1A2B3C4D的值,而Value指的就是 : 100这个值。 : 许多教科书,把地址1A2B3C4D这个值称为Value,我以为是不妥的。如果这样,那100这 : 个值称什么呢?
|
r********r 发帖数: 208 | 33 to answer your question: both are "pass by value".
【在 x*****p 的大作中提到】 : 其实这就是对Reference和Value的定义的歧义。Reference指的就是一个Object的地址 : ,当然也是一个值。可Value一般指的是这个地址的内存中所对应的内容。 : 举个例子。有一个十六进制的地址1A2B3C4D,这个地址对应的内存空间存了一个数是 : 100。那么,我们称的Reference,指的就是这个地址1A2B3C4D的值,而Value指的就是 : 100这个值。 : 许多教科书,把地址1A2B3C4D这个值称为Value,我以为是不妥的。如果这样,那100这 : 个值称什么呢?
|
x*****p 发帖数: 1707 | 34 你要这么说,我就无语了。地址1A2B3C4D叫Value,里面的内容100也叫Value。如果你
认为都称为pass by valu没什么不对,那就没什么好争了。至少对初学者来说,是看的
一头雾水。
【在 r********r 的大作中提到】 : to answer your question: both are "pass by value".
|
x*****p 发帖数: 1707 | 35 那请问,如果我们想传入1A2B3C4D这个地址对应的值100,那该称为pass by 什么?
value"
【在 r********r 的大作中提到】 : "1A2B3C4D" is the value of the reference. Therefore, this is "pass by value" : ; : "pass by reference" means "pass the address of the reference", and the : reference's value is 1A2B3C4D.
|
x*****p 发帖数: 1707 | 36 你这么说本没什么不对,懂的人心知肚明。但对初学者来说,你不觉得会学的一头雾水
么?
【在 w**z 的大作中提到】 : 你愿怎么叫都无所谓,只要明白到底发生什么就行了。
|
f*******b 发帖数: 520 | 37 唉,JAVA这个刚开始真心不习惯,今天copy一个数组也出了这个问题,要改成array.
clone()。 |
H**r 发帖数: 10015 | 38 core Java好像也是这样说的(vol 1)
【在 P***k 的大作中提到】 : 记得好像是thinking in java写过,java所有都视为pass by value.没有pass by : reference.
|
z****e 发帖数: 54598 | 39 array.clone
【在 f*******b 的大作中提到】 : 唉,JAVA这个刚开始真心不习惯,今天copy一个数组也出了这个问题,要改成array. : clone()。
|
H**r 发帖数: 10015 | |
|
|
H**r 发帖数: 10015 | 41 地址也可以是value啊
这个如果换C++可以是pass by reference也可以是pass by value。
Java只有pass by value所以这个情况放在Java里只能是pass by value
【在 x*****p 的大作中提到】 : 那请问,如果我们想传入1A2B3C4D这个地址对应的值100,那该称为pass by 什么? : : value"
|
g*****g 发帖数: 34805 | 42 没一个说到点子上。一个return,这个世界清静了。没有side effect的方法其实更方
便。而且可以串起来写。可以少定义很多临时变量。
Object o = "Hello";
o=mutate(o);
System.out.println(o);
private Object mutate(Object o)
{
o = "Goodbye";
return o;
} |
f*******b 发帖数: 520 | 43
好虫大牛果然名不虚传。佩服。。
【在 g*****g 的大作中提到】 : 没一个说到点子上。一个return,这个世界清静了。没有side effect的方法其实更方 : 便。而且可以串起来写。可以少定义很多临时变量。 : Object o = "Hello"; : o=mutate(o); : System.out.println(o); : private Object mutate(Object o) : { : o = "Goodbye"; : return o; : }
|
x*****p 发帖数: 1707 | 44 你这个更是跑题了。大家讨论的就是要让一个参数同时成为输入和输出。你生成一个返
回值,对这个问题固然没错,但如果处理多个返回值呢?对于多个返回值,我们只能在
参数上想办法,因为参数可以任意多人,同时作为输入和输出,就达到多个返回值的效
果。
【在 g*****g 的大作中提到】 : 没一个说到点子上。一个return,这个世界清静了。没有side effect的方法其实更方 : 便。而且可以串起来写。可以少定义很多临时变量。 : Object o = "Hello"; : o=mutate(o); : System.out.println(o); : private Object mutate(Object o) : { : o = "Goodbye"; : return o; : }
|
g*****g 发帖数: 34805 | 45 为嘛那么死脑筋呢,简单的,上个pair,复杂的,定义个类作为输出就得。这才是java
的正常写法。
side effect不是不允许,但都是为了性能的场合,写多了可读性差。
如果你比较过guava和jdk里对collections的处理,你就明白我说啥了。guava都返回
collection,从而简化了处理,而jdk则繁琐得多。
【在 x*****p 的大作中提到】 : 你这个更是跑题了。大家讨论的就是要让一个参数同时成为输入和输出。你生成一个返 : 回值,对这个问题固然没错,但如果处理多个返回值呢?对于多个返回值,我们只能在 : 参数上想办法,因为参数可以任意多人,同时作为输入和输出,就达到多个返回值的效 : 果。
|
x*****p 发帖数: 1707 | 46 越跑越远了,连第三方的库都搬出来了。那还讨论什么呀。你觉得不方便,就另外写个
库呗。这世上各种各样的库太多了。
java
【在 g*****g 的大作中提到】 : 为嘛那么死脑筋呢,简单的,上个pair,复杂的,定义个类作为输出就得。这才是java : 的正常写法。 : side effect不是不允许,但都是为了性能的场合,写多了可读性差。 : 如果你比较过guava和jdk里对collections的处理,你就明白我说啥了。guava都返回 : collection,从而简化了处理,而jdk则繁琐得多。
|
g*****g 发帖数: 34805 | 47 我没有扯远,我提的还是no side effect,你用过guava就明白我说什么。
【在 x*****p 的大作中提到】 : 越跑越远了,连第三方的库都搬出来了。那还讨论什么呀。你觉得不方便,就另外写个 : 库呗。这世上各种各样的库太多了。 : : java
|
z*******3 发帖数: 13709 | 48 我一般也是这种写法
如果是直接在原地址上做修改的话
我习惯用decorate作为方法名
比较恰如其分地描述方法的作用
【在 g*****g 的大作中提到】 : 没一个说到点子上。一个return,这个世界清静了。没有side effect的方法其实更方 : 便。而且可以串起来写。可以少定义很多临时变量。 : Object o = "Hello"; : o=mutate(o); : System.out.println(o); : private Object mutate(Object o) : { : o = "Goodbye"; : return o; : }
|
n*******k 发帖数: 100 | |