Redian新闻
>
《Halloween周末秀》-- 双满月小怪物
avatar
《Halloween周末秀》-- 双满月小怪物# NextGeneration - 我爱宝宝
f*b
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"呀?
avatar
q*o
2
双满月啦,又是万盛儿童节,摇身一变可爱的小怪物。明年再过节,就可以提个小篮子
歪歪扭扭出去敲门要好吃的啦。爸爸还搬来了个怪叔叔,放在宝宝跟前,好好笑呀好好
笑。嘻嘻。。。嘻嘻。。。嘻嘻。。。
过节真好~~
avatar
c*o
3
听说java里面都是reference啊
avatar
f*b
4

我看到的是不管什么java都是pass by value, 所以当我pass "GoodBye"时只是改变了
parameter的值,没能触动到之前定义的reference :(

【在 c******o 的大作中提到】
: 听说java里面都是reference啊
avatar
g*e
5


【在 c******o 的大作中提到】
: 听说java里面都是reference啊
avatar
v*d
6
java 是pass by value, 不过value是一个reference的值。o = "Goodbye"把一个新的
reference给了o, 当然不会生效。
至于怎么显示"Goodbye", String本身就是immutable的, 无解,除非你搞个
StringBuilder.

【在 f*******b 的大作中提到】
:
: 我看到的是不管什么java都是pass by value, 所以当我pass "GoodBye"时只是改变了
: parameter的值,没能触动到之前定义的reference :(

avatar
g*G
7
你一开始声明了一个string hello, 然后声明了o,这个o是一个object的引用,这个引
用指向hello这个string
然后调用mutate,传进去的其实是o这个引用地址的一个copy
你无论在nutate里如何操作这个引用地址,函数外的o的引用还是不会变,始终指向
hello
你没法通过函数改这个
因为string是immutable的
如果o指向的不是string是一个你自定义的类
那么你在mutate里改o本身的内容,是可以反映出来的
avatar
s*n
8
楼上正解!!!
用数组就能试出来, 输出结果为2.
int[] x = {0};
testRef(x);
System.out.println(x[0]);
public static void testRef(int[] y){
y[0] = 2;
}
avatar
f*g
9
请问各位,反转链表,用recursion来写,java 应该如何写?我一直觉得应该新建一个
类来wrap node 才能做到,比如下面,一直觉得这种方法不是很clean, 请问有更好的
方法吗? 不用新建类的
class WrapperNode{
ListNode node;
}
avatar
D*6
10
弄个dummyhead就好了。
avatar
f*b
11
多谢大牛,
刚试了不仅是String,如果是int也不行。但是像你说的一样自定义的类是可以改动的。
只有数组或是自定义的类,在指向的他们的值的时候改他们的值,才可以改动。如果只
是在函数里单纯的赋值是不奏效的。
avatar
g*G
12
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;
: }

avatar
g*G
13
String and int/long/char ... are different.
String is immutable, int/long/char/short ... are primitive types.

的。

【在 f*******b 的大作中提到】
: 多谢大牛,
: 刚试了不仅是String,如果是int也不行。但是像你说的一样自定义的类是可以改动的。
: 只有数组或是自定义的类,在指向的他们的值的时候改他们的值,才可以改动。如果只
: 是在函数里单纯的赋值是不奏效的。

avatar
s*r
14
Wrapper一下
avatar
s*n
15

弱弱的问下,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;

avatar
f*g
16
能详细解释一下吗?谢谢啦

【在 D****6 的大作中提到】
: 弄个dummyhead就好了。
avatar
f*g
17
面试官问的阿,我也没有办法啊,哎,找个工作真辛苦

【在 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;

avatar
z*e
18
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;
avatar
D*6
19
其实就是用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;
avatar
f*g
20
这个方法很聪明啊,多谢。

【在 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;

avatar
f*g
21
你的这个方法不错,避免了内部修改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;

avatar
z*e
22
前面添加一个头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){

avatar
h*6
23
把楼主的代码翻译成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。
avatar
f*b
24

大牛转的太棒了,关键是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);

avatar
z*e
25
java的内存管理是交给jvm去做的
如果你想操作内存地址的话,那还是回去用c

【在 f*******b 的大作中提到】
:
: 大牛转的太棒了,关键是C++有&可以用,c#有 ref 和 out, JAVA的话就麻烦许多,有
: 没有什么简便的方法替代&的?

avatar
x*p
26
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";
: }

avatar
x*p
27
The above example proves that Java is pass by reference.
avatar
w*z
28
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.
avatar
x*p
29
其实这就是对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 .
avatar
w*z
30
你愿怎么叫都无所谓,只要明白到底发生什么就行了。

【在 x*****p 的大作中提到】
: 其实这就是对Reference和Value的定义的歧义。Reference指的就是一个Object的地址
: ,当然也是一个值。可Value一般指的是这个地址的内存中所对应的内容。
: 举个例子。有一个十六进制的地址1A2B3C4D,这个地址对应的内存空间存了一个数是
: 100。那么,我们称的Reference,指的就是这个地址1A2B3C4D的值,而Value指的就是
: 100这个值。
: 许多教科书,把地址1A2B3C4D这个值称为Value,我以为是不妥的。如果这样,那100这
: 个值称什么呢?

avatar
w*z
31
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这
: 个值称什么呢?

avatar
P*k
32
记得好像是thinking in java写过,java所有都视为pass by value.没有pass by
reference.
avatar
r*r
33
"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这
: 个值称什么呢?

avatar
r*r
34
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这
: 个值称什么呢?

avatar
x*p
35
你要这么说,我就无语了。地址1A2B3C4D叫Value,里面的内容100也叫Value。如果你
认为都称为pass by valu没什么不对,那就没什么好争了。至少对初学者来说,是看的
一头雾水。

【在 r********r 的大作中提到】
: to answer your question: both are "pass by value".
avatar
x*p
36
那请问,如果我们想传入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.

avatar
x*p
37
你这么说本没什么不对,懂的人心知肚明。但对初学者来说,你不觉得会学的一头雾水
么?

【在 w**z 的大作中提到】
: 你愿怎么叫都无所谓,只要明白到底发生什么就行了。
avatar
f*b
38
唉,JAVA这个刚开始真心不习惯,今天copy一个数组也出了这个问题,要改成array.
clone()。
avatar
H*r
39
core Java好像也是这样说的(vol 1)

【在 P***k 的大作中提到】
: 记得好像是thinking in java写过,java所有都视为pass by value.没有pass by
: reference.

avatar
z*e
40
array.clone

【在 f*******b 的大作中提到】
: 唉,JAVA这个刚开始真心不习惯,今天copy一个数组也出了这个问题,要改成array.
: clone()。

avatar
H*r
42
地址也可以是value啊
这个如果换C++可以是pass by reference也可以是pass by value。
Java只有pass by value所以这个情况放在Java里只能是pass by value

【在 x*****p 的大作中提到】
: 那请问,如果我们想传入1A2B3C4D这个地址对应的值100,那该称为pass by 什么?
:
: value"

avatar
g*g
43
没一个说到点子上。一个return,这个世界清静了。没有side effect的方法其实更方
便。而且可以串起来写。可以少定义很多临时变量。
Object o = "Hello";
o=mutate(o);
System.out.println(o);
private Object mutate(Object o)
{
o = "Goodbye";
return o;
}
avatar
f*b
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;
: }

avatar
x*p
45
你这个更是跑题了。大家讨论的就是要让一个参数同时成为输入和输出。你生成一个返
回值,对这个问题固然没错,但如果处理多个返回值呢?对于多个返回值,我们只能在
参数上想办法,因为参数可以任意多人,同时作为输入和输出,就达到多个返回值的效
果。

【在 g*****g 的大作中提到】
: 没一个说到点子上。一个return,这个世界清静了。没有side effect的方法其实更方
: 便。而且可以串起来写。可以少定义很多临时变量。
: Object o = "Hello";
: o=mutate(o);
: System.out.println(o);
: private Object mutate(Object o)
: {
: o = "Goodbye";
: return o;
: }

avatar
g*g
46
为嘛那么死脑筋呢,简单的,上个pair,复杂的,定义个类作为输出就得。这才是java
的正常写法。
side effect不是不允许,但都是为了性能的场合,写多了可读性差。
如果你比较过guava和jdk里对collections的处理,你就明白我说啥了。guava都返回
collection,从而简化了处理,而jdk则繁琐得多。

【在 x*****p 的大作中提到】
: 你这个更是跑题了。大家讨论的就是要让一个参数同时成为输入和输出。你生成一个返
: 回值,对这个问题固然没错,但如果处理多个返回值呢?对于多个返回值,我们只能在
: 参数上想办法,因为参数可以任意多人,同时作为输入和输出,就达到多个返回值的效
: 果。

avatar
x*p
47
越跑越远了,连第三方的库都搬出来了。那还讨论什么呀。你觉得不方便,就另外写个
库呗。这世上各种各样的库太多了。

java

【在 g*****g 的大作中提到】
: 为嘛那么死脑筋呢,简单的,上个pair,复杂的,定义个类作为输出就得。这才是java
: 的正常写法。
: side effect不是不允许,但都是为了性能的场合,写多了可读性差。
: 如果你比较过guava和jdk里对collections的处理,你就明白我说啥了。guava都返回
: collection,从而简化了处理,而jdk则繁琐得多。

avatar
g*g
48
我没有扯远,我提的还是no side effect,你用过guava就明白我说什么。

【在 x*****p 的大作中提到】
: 越跑越远了,连第三方的库都搬出来了。那还讨论什么呀。你觉得不方便,就另外写个
: 库呗。这世上各种各样的库太多了。
:
: java

avatar
z*3
49
我一般也是这种写法
如果是直接在原地址上做修改的话
我习惯用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;
: }

相关阅读
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。