Java按值(或按引用)返回引用
考虑以下代码:Java按值(或按引用)返回引用,java,Java,考虑以下代码: package Prova; import java.util.ArrayList; public class Prova { private ArrayList<String> people; public Prova() { people=new ArrayList<String> (); } public ArrayList<String> getPeople (){
package Prova;
import java.util.ArrayList;
public class Prova
{
private ArrayList<String> people;
public Prova() {
people=new ArrayList<String> ();
}
public ArrayList<String> getPeople (){
return people;
}
public static void main(String[] args) {
Prova p=new Prova();
p.go();
}
public void go(){
ArrayList<String> temp=getPeople();
temp.add("jack");
System.out.print(getPeople());
}
}
Prova包;
导入java.util.ArrayList;
公共类普罗瓦
{
私人ArrayList人;
公共Prova(){
people=newarraylist();
}
公共数组列表getPeople(){
还人,;
}
公共静态void main(字符串[]args){
Prova p=新Prova();
p、 go();
}
公开作废go(){
ArrayList temp=getPeople();
临时添加(“千斤顶”);
System.out.print(getPeople());
}
}
上面印着“杰克”
为什么??这不违反封装吗?如何按值返回它?您需要进行防御性编程。有几个备选方案可供考虑
- 不要对外公开列表,而是公开应用于列表的方法,例如
- 返回不可变对象或对象的副本。例如:
public-List-getPeople{
返回新的ArrayList(人);
}
至于原因,其他帖子已经解释过了。传递到
ArrayList
的引用的值(更改值不会更改原始引用)。但是,列表本身包含对其对象的可修改引用 Java总是按值传递:
public List<String> getPeople() {
return Collections.unmodifiableList(people);
}
public List getPeople(){
返回集合。不可修改列表(人);
}
我建议大家看看Joshua Bloch的优秀著作《高效Java(第二版)》,“第39项:在需要时制作防御性拷贝”。不变性很迷人,但与制作防御性拷贝一样,它可能会变得昂贵。标准java集合并非设计为不变的数据结构。因此,如果你能像约翰·斯约伯格建议的那样去做,而不公开名单,那就太好了
但您也应该考虑为什么需要执行如此高级别的封装。您是否将类公开为公共API?如果没有,如果您很好地了解和控制类的客户机,那么太多的封装可能是不切实际的。请记住,封装/信息隐藏与安全性关系不大,而更多的是向客户机提供简洁明确的API
Java本质上是“按值传递”,与通常的意思有一个小但显著的区别,即它实际上是“按参考值传递”。 因此,当您处理Java类型(JVM的类公民,非基本类型)时,下面这样的声明基本上意味着您将获得类型为MyClass
的引用referenceToMyObject
的副本,指向JVM堆内存中相同的特定MyClass
对象实例
public class SomeClass {
private MyClass referenceToMyClassInstance = new MyClass("instanceId-1");
public MyClass getMyClassInstance() {
return referenceToMyClassInstance;
}
}
因此,在您的示例中,您基本上获得了指向同一ArrayList
实例的引用副本,调用getPeople()
的任何人现在都可以随意更改实际实例,可能会破坏应封装的状态
因此,您应该返回ArrayList的一个副本,或者用不可修改的DecoratorCollections.unmodifiableList(人员)包装它
Java在处理对象时总是按引用传递。代码所做的只是验证这一事实。那么你到底期待什么回来?@Churk!如果它是通过引用传递的,getPeople()=…
可以将成员更改为指向另一个ArrayList。对于论点传递,类似的反例是存在的,并且在我链接的问题中有十几个(更不用说几十个重复的问题了)。我只想重申@delnan的观点。在Java中,引用(基本上)是将指针的值传递给objectCollections。不可修改列表(人员)一点也不昂贵——它只是一个简单的包装器。是的,但它是原始集合的视图。因此,修改原始视图将反映在视图中。你应该确定那是你想要的。我的意思是,这与制作防御性拷贝非常不同。
public List<String> getPeople() {
return Collections.unmodifiableList(people);
}
public class SomeClass {
private MyClass referenceToMyClassInstance = new MyClass("instanceId-1");
public MyClass getMyClassInstance() {
return referenceToMyClassInstance;
}
}