gpt4 book ai didi

java - 返回 java 不可变结果意味着什么?

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:40:51 24 4
gpt4 key购买 nike

“返回原始数据的不可变接口(interface)。然后你可以更改对象中的字段,但调用者不能,除非他通过转换作弊。你只公开你希望用户拥有的方法。对类做同样的事情是更棘手,因为子类必须公开其父类(super class)所做的一切”

他的意思是你可以作弊,为什么子类很棘手?

来源:http://mindprod.com/jgloss/immutable.html

最佳答案

您提供一个没有突变方法的接口(interface)。然后,您提供只有创建者知道的可变实现。

public interface Person
{
String getName();
}

public class MutablePerson implements Person
{
private String name;

public MutablePerson(String name)
{
this.name = name;
}

@Override
public String getName()
{
return name;
}

public void setName(String name)
{
this.name = name;
}
}

在这一点上,如果你到处都返回Person对象,那么有人修改返回对象的唯一方法就是欺骗并将其转换回MutablePerson。实际上,除非代码完全被破解,否则可变对象将变为不可变对象(immutable对象)。

Person person = new MutablePerson("picky");
// someone is cheating:
MutablePerson mutableAgain = (MutablePerson)person;
mutableAgain.setName("Phoenix");

// person.getName().equals("Phoenix") == true

当不与一群注意到真正的实现是可变的年轻程序员打交道时,他们可以转换它来改变它,那么你就提供了不变性的安全性以及能够将它放在一起而无需无尽的构造函数,或使用 Builder(实际上,可变版本是 Builder)。避免开发人员滥用可变版本的一个好方法是将可变版本保留为包私有(private),这样只有包知道它。这个想法的负面影响是,这只有在将在同一个包中实例化时才有效,这可能是这种情况,但在 DAO 与多个包定义的实现(例如, 、MySQL、Oracle、Hibernate、Cassandra 等,都返回相同的东西,并希望彼此分开以避免弄乱它们的包)。

这里真正的关键是人们永远不应该从 Mutable 对象构建,除非是为了实现更深层次的接口(interface)。如果您正在扩展,然后返回一个不可变的子类,那么根据定义,如果它公开一个可变对象,它就不是不可变的。例如:

public interface MyType<T>
{
T getSomething();
}

public class MyTypeImpl<T> implements MyType<T>
{
private T something;

public MyTypeImpl(T something)
{
this.something = something;
}

@Override
public T getSomething()
{
return something;
}

public void setSomething(T something)
{
this.something = something;
}
}

public interface MyExtendedType<T> extends MyType<T>
{
T getMore();
}

public class MyExtendedTypeImpl<T>
extends MyTypeImpl<T>
implements MyExtendedType<T>
{
private T more;

public MyExtendedTypeImpl(T something, T more)
{
super(something);

this.more = more;
}

@Override
public T getMore()
{
return more;
}

public void setMore(T more)
{
this.more = more;
}
}

老实说,这就是 Java 中的 Collection 应该实现的方式。只读接口(interface)可以取代 Collections.unmodifiable 实现,这样就不会让人意外地使用可变对象的不可变版本。换句话说,你永远不应该隐藏不变性,但你可以隐藏可变性。

然后,他们可以散布真正无法修改的不可变实例,这将使开发人员保持诚实。同样,我可能希望在某处看到上述接口(interface)的不可变版本(使用更好的名称):

public class MyTypeImmutable<T> implements MyType<T>
{
private final T something;

public MyTypeImmutable(T something)
{
this.something = something;
}

@Override
public T getSomething()
{
return something;
}
}

关于java - 返回 java 不可变结果意味着什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12945837/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com