我不想做那种深奥的复制方式。
比如说,我有一个可变类型的字段,例如x,y,z坐标。偶尔,我需要把这个领域暴露给一些观众。我希望它是只读的。我记得读过一些类似包装的东西来做这些事情,但我不记得细节。
x,y,z坐标的例子可能太简单了,因为x,y,z是原语类型。因此,getX()总是返回一个副本。
我想要一个通解,即使x,y,z字段是另一种可变类型。
有人能帮忙吗?
编辑
public class Client
{
    public static final Holder holder = new Holder();
    public static void main(String[] args)
    {
        UserWrapper user = holder.getUser();
        System.out.println(user);               //UserWrapper{user=User{address=Address{street='street 101'}}}
        user.getAddress().setStreet("mars");    //UserWrapper{user=User{address=Address{street='mars'}}}
        System.out.println(user);
    }
}public class Holder
{
    private User user;
    public Holder()
    {
        user = new User();
        Address address = new Address();
        address.setStreet("street 101");
        user.setAddress(address);
    }
    public UserWrapper getUser()
    {
        return new UserWrapper(user);
    }
}public class User
{
    private Address address;
    public Address getAddress()
    {
        return address;
    }
    public void setAddress(Address address)
    {
        this.address = address;
    }
}public class UserWrapper
{
    private User user;
    public UserWrapper(User user)
    {
        this.user = user;
    }
    public Address getAddress()
    {
        return user.getAddress();
    }
}编辑:归功于I don't know who(他删除了答案),我发现他在最初的文章中提到的此链接非常有用。
发布于 2017-11-28 07:23:42
传统方式:
还有其他人,但这应该会让你开始。
发布于 2017-11-28 07:04:30
Java中没有内置机制使您能够做到这一点。通常,如果您移动实例,您可以:
由于您不想/不能选择这两种方式,所以您需要使用另一种方法。根据您的需求和类结构的复杂程度,有很多不同的实现方法,但是一般的方法是发布一个不变的包装器,而不是原来的包装。
下面是一些示例:
public class XYZ {
    public int x, y, z;
}
public class XYZWrapper {
    private XYZ xyz;
    public XYZWrapper(XYZ xyz) {
        this.xyz = xyz;
    }
    public int getX() { return x; }
    public int getY() { return y; }
    public int getZ() { return z; }
}
public class Address {
    public String name;
    public XYZ xyz;
}
public class AddressWrapper {
    private String name; // Note that this could be public since any String is immutable
    private XYZWrapper xyzWrapper;
    public AddressWrapper(String name, XYZ xyz) {
        this.name = name;
        this.xyzWrapper = new XYZWrapper(xyz);
    }
    public String getName() { 
        return name;
    }
    public XYZWrapper getXYZWrapper() { 
        return xyzWrapper;
    }
}现在,如果您使用的不是XYZ和Address类,您可以使用接口,您可以有两个实现(例如,XYZMutable & XYZImmutable),它将允许您抽象出要返回的类的类型,还将使您能够从XYZMutable实例创建XYZImmutable实例(假设接口只定义&所有getter方法)。
有关此方法的另一个注意事项(特别是如果您使用接口作为首选方法):即使您有一个复杂的类层次结构,也可以相对轻松地创建一个生成器类,该类接收接口实例、可变实现实例并返回一个不变的实现实例作为返回值。
发布于 2017-11-28 07:38:01
也许你在想"抄写即写“这个成语。这允许您避免复制,除非您必须这样做。通常不推荐使用它,因为它不是线程安全的,除非您使用同步,这会不必要地减缓单线程应用程序的速度。
它的工作方式是保持其内部数据的引用计数;类似于以下未经测试的代码:
public class User
{
    private int addressReferenceCount;
    private Address address;
    public User(Address address) {
        addressReferenceCount = 0;
        this.address = address;
    }
    public Address getAddress() {
        addressReferenceCount++;
        return address;
    }
    public void setAddress(Address address)
    {
        if (addressReferenceCount == 0) {
            this.address = address;
        }
        else {
            this.address = new Address(address);
            addressReferenceCount = 0;
        }
    }
}这可以确保这样的用户代码在必要时获得不同的地址:
User u = new User(new Address("1 Acacia Avenue"));
Address oldAddress = u.getAddress();
Address stillOldAddress = u.getAddress();
u.setAddress(new Address("2 Acacia Avenue"));
Address newAddress = u.getAddress();
assert (oldAddress == stillOldAddress); // both refer to same object
assert (oldAddress != newAddress);https://stackoverflow.com/questions/47524919
复制相似问题