问题描述
我编写了一段返回我想要的结果的代码,但我不确定这两种代码变体之间的确切区别是:
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);
我调用方法的类是:Notes类(Notes.java文件)
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如何“知道”项目添加到哪个列表?
1楼
Java如何“知道”项目添加到哪个列表?
它不需要“知道”:您正在查看对堆中相同单个对象的两个引用。
实际参数userRhythm
是一个按值传递给addEight
的对象引用 , (另请参阅: )
所以:
-
在第一种情况下,你是
- 按值传递对象引用
-
对所述对象执行
add
,这有副作用
-
在第二种情况下,你是
- 按值传递对象引用
-
对所述对象执行
add
,这有副作用 -
将返回的对象引用分配给
userRhythm
,但它们是相同的,因为返回的对象引用是实际参数,因此它没有做很多事情。
如果你改为:
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);
你能说出原因吗?
作为旁注,实际上返回任何东西并不是非常有用。
你可以通过使它成为一个void
方法更好。
你正在处理引用 ,因此你不需要return
东西,你方法的就是你想要的。
2楼
假设你写的是这样的:
ArrayList<String> userRhythm = new ArrayList<String>();
ArrayList<String> userRhythm2 = Notes.addEight(userRhythm);
System.out.println(userRhythm2);
在这种情况下, userRhythm
和userRhythm2
将引用相同的 ArrayList
。
只有一个列表,但有多个引用。
你怎么解决这个问题?
因为您正在修改参数,所以不需要返回它。 您可以将您的方法重写为
public static void addEight(ArrayList<String> userRhythm) {
userRhythm.add("n8");
}
这在语义上更有意义,因为大多数操作根本不返回任何内容。
3楼
您的方法将列表作为参数,向该列表添加元素,然后返回该列表。 因此,您的两个代码段在功能上是等效的。
如果方法返回的另一个列表不是它作为参数接收的列表,它们将不相等。 例如:
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);
会打印[]
(空列表),因为它会将方法返回的新空列表分配给userRhythm
并打印出来。
而第二个片段:
ArrayList<String> userRhythm = new ArrayList<String>();
Notes.addEight(userRhythm);
System.out.println(userRhythm);
将打印[n8]
,因为它忽略方法返回的空列表,并打印该方法已修改的原始列表。
从方法返回一个参数没有多大意义:调用者显然已经有了对该参数的引用,因此返回它是无用且令人困惑的。
你最好让你的方法返回void
。
4楼
两者之间的区别在于,在第一种情况下,您将函数的返回值分配给userRythym
变量,而在第二种情况下,您将丢弃函数的返回值。
它们的行为相同,因为函数的返回值是userRythym
,因此赋值(在第一种情况下)只是将变量设置为已有的值。
5楼
ArrayList
是可变的,因此您不应返回值/重新分配arraylist引用(在现有代码中)。
如果您的方法实际返回一个ArrayList
( List
),将ArrayList
( List
)作为参数,那么您可以使用返回的值。
例如:
list = someClassInstance.toImmutableList(list); // toImmutableList() returns an immutable representation of list passed as argument
6楼
从功能的角度来看,两种方法都完全相同:它们将"n8"
添加到作为参数传递的列表中。
唯一的区别在于return
语句:第一个方法不返回任何内容,而第二个方法返回对作为参数传递的相同列表的引用 。
虽然这一切看起来很明显,但使用第二个选项可以让您执行以下操作:
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
)。
7楼
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] - 如果你得到回报价值
[] - 如果没有得到返回值
8楼
Java如何“知道”项目添加到哪个列表?
您的代码中只有一个列表。 它通过引用传递给你的addEight()方法,然后返回引用。
9楼
也就是说,当我使用addEight()方法将一个项添加到ArrayList并将其返回到main时,我是否必须使用带赋值运算符的语句[...]或者我可以像这样调用方法,它将添加一个项目到列表。
如果将对象引用传递给方法 - 并且每个Java值都是基本( int
, char
等)或对象引用 - 那么该方法可以更改引用对象的任何可修改属性,以及可以通过对对象的任何引用来观察修改。
这样的方法也可以返回对该对象的引用,但这是一个完全独立的问题。
始终可以通过对该对象的任何引用来访问对象的当前状态。
这两个陈述有什么区别,因为最后它们都打印出相同的结果? 如果我只使用Notes.addEight(userRhythm); 而不是userRhythm = Notes.addEight(userRhythm); Java如何“知道”项目添加到哪个列表?
区别在于,在一种情况下,您将Notes.addEight()
返回的引用分配给main()
方法的局部变量userRhythm
,而在另一种情况下userRhythm
。
因为Notes.addEight()
返回传递给它的引用的副本,所以这userRythm
相同的值重新分配给它已经拥有的userRythm
。
这也没用,但也没有害处。