从方法返回值时,这两个语句有什么区别?
What is the difference between these two statements when a value is returned from a method?
我写了一段代码,return是我想要的结果,但我不确定这两种代码变体之间的确切区别是什么:
ArrayList<String> userRhythm = new ArrayList<String>();
userRhythm = Notes.addEight(userRhythm);
System.out.println(userRhythm);
或者:
ArrayList<String> userRhythm = new ArrayList<String>();
Notes.addEight(userRhythm);
System.out.println(userRhythm);
而class我从中调用了一个方法是:Notes class (Notes.java file)
import java.util.ArrayList;
public class Notes {
public static ArrayList<String> addEight(ArrayList<String> userRhythm) {
userRhythm.add("n8");
return userRhythm;
}
}
也就是说,当我使用 addEight()
方法将一个项目添加到 ArrayList 并将其添加到 main 时,我是否必须像这样使用带有赋值运算符的语句:
userRhythm = Notes.addEight(userRhythm);
或者我可以像这样调用方法,它会向列表中添加一个项目。
Notes.addEight(userRhythm);
这两个语句有什么区别,因为它们最终都打印出相同的结果?如果我只使用 Notes.addEight(userRhythm);
而不是 userRhythm = Notes.addEight(userRhythm);
Java 如何“知道”一个项目被添加到哪个列表?
假设你是这样写的:
ArrayList<String> userRhythm = new ArrayList<String>();
ArrayList<String> userRhythm2 = Notes.addEight(userRhythm);
System.out.println(userRhythm2);
在这种情况下,userRhythm
和 userRhythm2
将引用 相同的 ArrayList
。只有一个列表,但有多个引用。
如何解决这个问题?
因为您正在修改参数,所以不需要return。您可以将方法重写为
public static void addEight(ArrayList<String> userRhythm) {
userRhythm.add("n8");
}
这在语义上更有意义,因为大多数 add 操作根本不 return 任何东西。
两者之间的区别在于,在第一种情况下,您将函数的 return 值分配给 userRythym
变量,而在第二种情况下,您丢弃函数的 return值。
它们的行为相同,因为函数的 return 值为 userRythym
,因此赋值(在第一种情况下)只是将变量设置为它已有的值。
您的方法将一个列表作为参数,向该列表添加一个元素,然后 returns 该列表。所以你的两个代码片段在功能上是等价的。
如果方法 returned 另一个 列表而不是它作为参数接收的列表,它们将不等价。例如:
public static ArrayList<String> addEight(ArrayList<String> userRhythm) {
userRhythm.add("n8");
return new ArrayList<String>();;
}
在那种情况下,第一个代码片段:
ArrayList<String> userRhythm = new ArrayList<String>();
userRhythm = Notes.addEight(userRhythm);
System.out.println(userRhythm);
将打印 []
(空列表),因为它将通过方法 return 编辑的新空列表分配给 userRhythm
并打印它。而第二个片段:
ArrayList<String> userRhythm = new ArrayList<String>();
Notes.addEight(userRhythm);
System.out.println(userRhythm);
将打印 [n8]
,因为它忽略了由该方法 return 编辑的空列表,并打印该方法已修改的原始列表。
从方法返回一个参数没有多大意义:调用者显然已经有一个对该参数的引用,所以 returning 它是无用且令人困惑的。你最好让你的方法 return void
.
ArrayList
是可变的,所以你不应该 return 一个值/重新分配 arraylist 引用(在你现有的代码中)。
如果您的方法实际上 return 是一个 ArrayList
(List
) 以 ArrayList
(List
) 作为参数,那么您可以使用returned 值。
示例:
list = someClassInstance.toImmutableList(list); // toImmutableList() returns an immutable representation of list passed as argument
See the difference between these two implementations by creating new object in addEight method
import java.util.ArrayList;
public class Notes {
public static ArrayList<String> addEight(ArrayList<String> userRhythm) {
userRhythm = new ArrayList<String>();
userRhythm.add("n8");
return userRhythm;
}
public static void main(String args[]){
ArrayList<String> userRhythm = new ArrayList<String>();
userRhythm = Notes.addEight(userRhythm);
System.out.println(userRhythm);
ArrayList<String> userRhythm1 = new ArrayList<String>();
Notes.addEight(userRhythm1);
System.out.println(userRhythm1);
}
}
输出:
[n8] -- 如果得到return值
[] - 如果您没有得到 return 值
how does Java “knows” to which list an item was added?
您的代码中只有 1 个列表。它通过引用传递给您的 addEight() 方法,然后 returns 引用。
how does Java “knows” to which list an item was added?
不需要 "know":您正在查看对堆中同一个对象的两个引用。
实参userRhythm
是一个对象引用按值传递给addEight
, as is the case in Java (see also: Is Java "pass-by-reference" or "pass-by-value"?)
所以:
- 第一种情况,你是
- 按值传递对象引用并且
- 在所述对象上执行
add
,它有副作用
- 在第二种情况下,你是
- 按值传递对象引用并且
- 在所述对象上执行
add
,它有副作用
- 将returned对象引用赋值给
userRhythm
,但是它们是一样的,因为returned对象引用是实参,所以不做a很划算。
如果你有:
public static ArrayList<String> addEight(ArrayList<String> userRhythm) {
userRhythm.add("n8");
return new ArrayList<String>();
}
然后这将产生预期的结果:
ArrayList<String> userRhythm = new ArrayList<String>();
Notes.addEight(userRhythm);
System.out.println(userRhythm);
这个不会:
ArrayList<String> userRhythm = new ArrayList<String>();
userRhythm = Notes.addEight(userRhythm);
System.out.println(userRhythm);
能说说为什么吗?
顺便说一句,事实上,它对 return 任何东西都没有太大用处。
将其设为 void
方法可能会更好。
您正在处理 引用 ,因此您不需要 return
东西,方法的 side effects 就是您想要的。
Namelly, when I add an item to ArrayList using addEight() method, and return it to the main, do I have to use statement with assignment operator [...] Or I could just call the method like this and it will add an item to the list.
如果将对象引用传递给方法——并且每个 Java 值要么是原始值(int
、char
等),要么是对象引用——然后该方法可以更改所引用对象的任何可修改属性,并且可以通过对该对象的任何引用来观察这些修改。这样的方法也可能 return 对该对象的引用,但这是一个完全不同的问题。始终可以通过对该对象的任何引用访问该对象的当前状态。
What is difference between these two statements, since in the end they both print same result? If I use only Notes.addEight(userRhythm); and not userRhythm = Notes.addEight(userRhythm); how does Java “knows” to which list an item was added?
区别仅在于,在一种情况下,您将由 Notes.addEight()
编辑的引用 return 分配给 main()
方法的局部变量 userRhythm
,而在另一种情况下你没有。因为 Notes.addEight()
return 是传递给它的引用的副本,所以这具有将相同的值重新分配给它已经具有的 userRythm
的效果。这没有用,但也无害。
从功能的角度来看,这两种方法的作用完全相同:它们将 "n8"
添加到作为参数传递的列表中。
唯一的区别在于 return
语句:第一个方法不 return 任何东西,而第二个 return 是 对相同内容的引用作为参数传递的 list。虽然这一切看起来很明显,但使用第二个选项可以让您执行以下操作:
ArrayList<String> list = new ArrayList<>();
boolean hasNote = Notes.addEight(list).contains("n8"); // true
这是否对您有用,将取决于您的具体问题。
一般来说,有多个引用指向同一个对象是没有意义的。考虑以下因素:
ArrayList<String> list1 = new ArrayList<>();
ArrayList<String> list2 = Notes.addEight(list1);
System.out.println("list1 == list2 ? " + (list1 == list2)); // true, they point to
// the same list
System.out.println("list1.equals(list2) ? " + (list1.equals(list2))); // true, since they
// not only contain
// the same
// elements, but
// also point to the
// same list
在这种情况下,让两个引用指向同一个列表似乎不是很有用,因为这样做就像这样:
ArrayList<String> list1 = new ArrayList<>();
ArrayList<String> list2 = Notes.addEight(list1);
ArrayList<String> list3 = list1;
System.out.println("list1 == list2 ? " + (list1 == list2)); // true
System.out.println("list1.equals(list2) ? " + (list1.equals(list2))); // true
System.out.println("list1 == list3 ? " + (list1 == list3)); // true
System.out.println("list1.equals(list3) ? " + (list1.equals(list2))); // true
现在,如果您的 Notes.addEight()
方法是这样实现的,情况会有所不同:
public static ArrayList<String> addEight(ArrayList<String> list) {
list.add("n8");
return new ArrayList<>(list); // NOTE THIS! A new ArrayList is being returned
}
如果我们调用这个新的 addEight()
方法,那么情况会有所不同:
ArrayList<String> list1 = new ArrayList<>();
ArrayList<String> list2 = Test.addEight(list1);
ArrayList<String> list3 = list1;
System.out.println("list1 == list2 ? " + (list1 == list2)); // false
System.out.println("list1.equals(list2) ? " + (list1.equals(list2))); // true
System.out.println("list1 == list3 ? " + (list1 == list3)); // true
System.out.println("list1.equals(list3) ? " + (list1.equals(list3))); true
如您所见,现在 list1
和 list2
是指向不同对象的引用(list1 == list2
是 false
),而 list1.equals(list2)
是 true
,因为两个列表包含相同顺序的相同元素(它们语义相等)。
然而,list1 == list3
是 true
,因为它们实际上指向同一个列表,由于 list3
的声明方式(list3
被分配给 list1
通过赋值运算符 =
).
我写了一段代码,return是我想要的结果,但我不确定这两种代码变体之间的确切区别是什么:
ArrayList<String> userRhythm = new ArrayList<String>();
userRhythm = Notes.addEight(userRhythm);
System.out.println(userRhythm);
或者:
ArrayList<String> userRhythm = new ArrayList<String>();
Notes.addEight(userRhythm);
System.out.println(userRhythm);
而class我从中调用了一个方法是:Notes class (Notes.java file)
import java.util.ArrayList;
public class Notes {
public static ArrayList<String> addEight(ArrayList<String> userRhythm) {
userRhythm.add("n8");
return userRhythm;
}
}
也就是说,当我使用 addEight()
方法将一个项目添加到 ArrayList 并将其添加到 main 时,我是否必须像这样使用带有赋值运算符的语句:
userRhythm = Notes.addEight(userRhythm);
或者我可以像这样调用方法,它会向列表中添加一个项目。
Notes.addEight(userRhythm);
这两个语句有什么区别,因为它们最终都打印出相同的结果?如果我只使用 Notes.addEight(userRhythm);
而不是 userRhythm = Notes.addEight(userRhythm);
Java 如何“知道”一个项目被添加到哪个列表?
假设你是这样写的:
ArrayList<String> userRhythm = new ArrayList<String>();
ArrayList<String> userRhythm2 = Notes.addEight(userRhythm);
System.out.println(userRhythm2);
在这种情况下,userRhythm
和 userRhythm2
将引用 相同的 ArrayList
。只有一个列表,但有多个引用。
如何解决这个问题?
因为您正在修改参数,所以不需要return。您可以将方法重写为
public static void addEight(ArrayList<String> userRhythm) {
userRhythm.add("n8");
}
这在语义上更有意义,因为大多数 add 操作根本不 return 任何东西。
两者之间的区别在于,在第一种情况下,您将函数的 return 值分配给 userRythym
变量,而在第二种情况下,您丢弃函数的 return值。
它们的行为相同,因为函数的 return 值为 userRythym
,因此赋值(在第一种情况下)只是将变量设置为它已有的值。
您的方法将一个列表作为参数,向该列表添加一个元素,然后 returns 该列表。所以你的两个代码片段在功能上是等价的。
如果方法 returned 另一个 列表而不是它作为参数接收的列表,它们将不等价。例如:
public static ArrayList<String> addEight(ArrayList<String> userRhythm) {
userRhythm.add("n8");
return new ArrayList<String>();;
}
在那种情况下,第一个代码片段:
ArrayList<String> userRhythm = new ArrayList<String>();
userRhythm = Notes.addEight(userRhythm);
System.out.println(userRhythm);
将打印 []
(空列表),因为它将通过方法 return 编辑的新空列表分配给 userRhythm
并打印它。而第二个片段:
ArrayList<String> userRhythm = new ArrayList<String>();
Notes.addEight(userRhythm);
System.out.println(userRhythm);
将打印 [n8]
,因为它忽略了由该方法 return 编辑的空列表,并打印该方法已修改的原始列表。
从方法返回一个参数没有多大意义:调用者显然已经有一个对该参数的引用,所以 returning 它是无用且令人困惑的。你最好让你的方法 return void
.
ArrayList
是可变的,所以你不应该 return 一个值/重新分配 arraylist 引用(在你现有的代码中)。
如果您的方法实际上 return 是一个 ArrayList
(List
) 以 ArrayList
(List
) 作为参数,那么您可以使用returned 值。
示例:
list = someClassInstance.toImmutableList(list); // toImmutableList() returns an immutable representation of list passed as argument
See the difference between these two implementations by creating new object in addEight method
import java.util.ArrayList;
public class Notes {
public static ArrayList<String> addEight(ArrayList<String> userRhythm) {
userRhythm = new ArrayList<String>();
userRhythm.add("n8");
return userRhythm;
}
public static void main(String args[]){
ArrayList<String> userRhythm = new ArrayList<String>();
userRhythm = Notes.addEight(userRhythm);
System.out.println(userRhythm);
ArrayList<String> userRhythm1 = new ArrayList<String>();
Notes.addEight(userRhythm1);
System.out.println(userRhythm1);
}
}
输出:
[n8] -- 如果得到return值
[] - 如果您没有得到 return 值
how does Java “knows” to which list an item was added?
您的代码中只有 1 个列表。它通过引用传递给您的 addEight() 方法,然后 returns 引用。
how does Java “knows” to which list an item was added?
不需要 "know":您正在查看对堆中同一个对象的两个引用。
实参userRhythm
是一个对象引用按值传递给addEight
, as is the case in Java (see also: Is Java "pass-by-reference" or "pass-by-value"?)
所以:
- 第一种情况,你是
- 按值传递对象引用并且
- 在所述对象上执行
add
,它有副作用
- 在第二种情况下,你是
- 按值传递对象引用并且
- 在所述对象上执行
add
,它有副作用 - 将returned对象引用赋值给
userRhythm
,但是它们是一样的,因为returned对象引用是实参,所以不做a很划算。
如果你有:
public static ArrayList<String> addEight(ArrayList<String> userRhythm) {
userRhythm.add("n8");
return new ArrayList<String>();
}
然后这将产生预期的结果:
ArrayList<String> userRhythm = new ArrayList<String>();
Notes.addEight(userRhythm);
System.out.println(userRhythm);
这个不会:
ArrayList<String> userRhythm = new ArrayList<String>();
userRhythm = Notes.addEight(userRhythm);
System.out.println(userRhythm);
能说说为什么吗?
顺便说一句,事实上,它对 return 任何东西都没有太大用处。
将其设为 void
方法可能会更好。
您正在处理 引用 ,因此您不需要 return
东西,方法的 side effects 就是您想要的。
Namelly, when I add an item to ArrayList using addEight() method, and return it to the main, do I have to use statement with assignment operator [...] Or I could just call the method like this and it will add an item to the list.
如果将对象引用传递给方法——并且每个 Java 值要么是原始值(int
、char
等),要么是对象引用——然后该方法可以更改所引用对象的任何可修改属性,并且可以通过对该对象的任何引用来观察这些修改。这样的方法也可能 return 对该对象的引用,但这是一个完全不同的问题。始终可以通过对该对象的任何引用访问该对象的当前状态。
What is difference between these two statements, since in the end they both print same result? If I use only Notes.addEight(userRhythm); and not userRhythm = Notes.addEight(userRhythm); how does Java “knows” to which list an item was added?
区别仅在于,在一种情况下,您将由 Notes.addEight()
编辑的引用 return 分配给 main()
方法的局部变量 userRhythm
,而在另一种情况下你没有。因为 Notes.addEight()
return 是传递给它的引用的副本,所以这具有将相同的值重新分配给它已经具有的 userRythm
的效果。这没有用,但也无害。
从功能的角度来看,这两种方法的作用完全相同:它们将 "n8"
添加到作为参数传递的列表中。
唯一的区别在于 return
语句:第一个方法不 return 任何东西,而第二个 return 是 对相同内容的引用作为参数传递的 list。虽然这一切看起来很明显,但使用第二个选项可以让您执行以下操作:
ArrayList<String> list = new ArrayList<>();
boolean hasNote = Notes.addEight(list).contains("n8"); // true
这是否对您有用,将取决于您的具体问题。
一般来说,有多个引用指向同一个对象是没有意义的。考虑以下因素:
ArrayList<String> list1 = new ArrayList<>();
ArrayList<String> list2 = Notes.addEight(list1);
System.out.println("list1 == list2 ? " + (list1 == list2)); // true, they point to
// the same list
System.out.println("list1.equals(list2) ? " + (list1.equals(list2))); // true, since they
// not only contain
// the same
// elements, but
// also point to the
// same list
在这种情况下,让两个引用指向同一个列表似乎不是很有用,因为这样做就像这样:
ArrayList<String> list1 = new ArrayList<>();
ArrayList<String> list2 = Notes.addEight(list1);
ArrayList<String> list3 = list1;
System.out.println("list1 == list2 ? " + (list1 == list2)); // true
System.out.println("list1.equals(list2) ? " + (list1.equals(list2))); // true
System.out.println("list1 == list3 ? " + (list1 == list3)); // true
System.out.println("list1.equals(list3) ? " + (list1.equals(list2))); // true
现在,如果您的 Notes.addEight()
方法是这样实现的,情况会有所不同:
public static ArrayList<String> addEight(ArrayList<String> list) {
list.add("n8");
return new ArrayList<>(list); // NOTE THIS! A new ArrayList is being returned
}
如果我们调用这个新的 addEight()
方法,那么情况会有所不同:
ArrayList<String> list1 = new ArrayList<>();
ArrayList<String> list2 = Test.addEight(list1);
ArrayList<String> list3 = list1;
System.out.println("list1 == list2 ? " + (list1 == list2)); // false
System.out.println("list1.equals(list2) ? " + (list1.equals(list2))); // true
System.out.println("list1 == list3 ? " + (list1 == list3)); // true
System.out.println("list1.equals(list3) ? " + (list1.equals(list3))); true
如您所见,现在 list1
和 list2
是指向不同对象的引用(list1 == list2
是 false
),而 list1.equals(list2)
是 true
,因为两个列表包含相同顺序的相同元素(它们语义相等)。
然而,list1 == list3
是 true
,因为它们实际上指向同一个列表,由于 list3
的声明方式(list3
被分配给 list1
通过赋值运算符 =
).