返回数组列表的 const 引用

发布于 2024-10-03 22:10:05 字数 600 浏览 2 评论 0原文

我真的很欣赏java的特性,我不想放弃使用它来解决下一个问题:

我有一个可能被继承的类,它的内部是一个private ArrayList arr;所以setter函数没问题,但是 getter 函数 return arr; 返回对该变量的引用,任何能够编辑我不想要的整个数组的人都没有任何意义!

在 C++ 中,我只需 return const arr; 并且它将返回对变量的常量引用。

我非常需要不要克隆或手动复制变量,因为有很多计算需要(只读变量)为什么在java中没有const返回???有什么办法可以避免复制吗?

ps (final ArrayListarr;) 不是一个选项,因为数组总是会更改大小或元素值。

如果我找不到解决办法,我威胁要回到 C++ 或将所有内容公开,你永远不应该得到我的软件:D


编辑:一个更重要的问题:我是否要求一些不好的东西(软件工程)明智的)我的意思是,如果 JAVA 创建者认为没有 const 引用(返回只读引用),那么我必须要求可以以其他方式处理的东西。或者我的程序设计是错误的我很困惑。

I really admire java features and I don't want to give up using it for the next problem:

I have a class that might be inherited, and inside of it is a private ArrayList arr; So the setter function is ok , but the getter function return arr; returns the reference to that variable which anyone capable of editing that whole array which I don't want and private wouldn't make any sense !

In C++ I would just return const arr; and it would return constant reference to the variable.

I so much need the variable not to be cloned or manually copied because there are so many calculations that require to (READ ONLY the variable) WHY there is no const returning in java ???? is there any way I could escape copying ?

p.s (final ArrayList<Integer> arr;) isn't an option cause that array always changes size or element values.

If I couldn't find a fix to that I'm threatening to go back to C++ or make everything public and you should never get my software :D


EDIT: one more important question: Am I asking for something that's not good (Software engineering wise) I mean if JAVA creators thought of not having const reference (returning Read only references) then I must be asking for something that can be handled in other way. or my program design is wrong I'm so confused.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

徒留西风 2024-10-10 22:10:05

包装返回值java.util.Collections.unmodifyingList。它不会复制数据,而是包装原始列表,并将只读操作委托给基础列表。修改列表的操作在运行时会通过 UnsupportedOperationException 被拒绝。

return arrayList;

不幸的是

return Collections.unmodifiableList(arrayList);

编译器不会强制执行只读约束。然而,它们将在运行时强制执行。

您还可以使用: unmodifyingSet unmodifyingMap, unmodifyingCollectionunmodifyingSortedSet,以及不可修改的SortedMap。如果这些还不够,您仍然可以从这种通用设计方法中获取灵感,并创建您自己的自定义只读包装类。

Wrap the return value with java.util.Collections.unmodifiableList. It does not make a copy of the data, but wraps the original list, and delegates read-only operations to the underlying list. Operations which would modify the list are rejected at runtime via UnsupportedOperationException.

Your

return arrayList;

becomes

return Collections.unmodifiableList(arrayList);

Unfortunately the read-only constraints won't be enforced by the compiler. They will, however, be enforced at runtime.

You also have available to you: unmodifiableSet, unmodifiableMap, unmodifiableCollection, unmodifiableSortedSet, and unmodifiableSortedMap. And if these are not enough, you can still take inspiration from this general design approach, and create your own custom read-only wrapper classes.

莳間冲淡了誓言ζ 2024-10-10 22:10:05

:) 你有几个选择:

  • 不要暴露 getter,只提供允许调用的方法,例如

    public void addToList(Object arg) { this.arr.add(arg);}

  • 返回不可变对象:

    public List getArr() { return Collections.unmodifyingList(this.arr); } }

:) You have several options:

  • Don't expose getter, provide only methods which are allowed to call, e.g.

    public void addToList(Object arg) { this.arr.add(arg);}

  • Return immutable object:

    public List getArr() { return Collections.unmodifiableList(this.arr); }

猥︴琐丶欲为 2024-10-10 22:10:05

您还可以使用 Google Guava 的不可变 集合。在这种情况下,您将存储 ImmutableList 在您的领域。

当然,如果您的类需要在内部修改此列表,那么使用 ImmutableList 可能是一个坏主意,因为您需要创建一个新的 ImmutableList 实例并每次将其重新分配给该字段...

但是当您知道对象构造后列表不会更改时,它就完美了。

不可变示例(对象构造后列表不会更改)

@Immutable
public final class Foo {

    @Nonnull
    private final ImmutableList<String> list;

    public Foo(@Nonnull List<String> list) {
        // you could also compute the appropriate list here
        // before assigning it to the field
        this.list = ImmutableList.copyOf(list);
    }


    public ImmutableList<String> getList() {
        return list;
    }
}

可变示例(列表只能使用 setter 进行修改)

public class Foo {

    @Nonnull
    private ImmutableList<String> list = ImmutableList.of();

    public ImmutableList<String> getList() {
        return list;
    }

    public void setList(@Nonnull List<String> list) {
        this.list = ImmutableList.copyOf(list);
    }
}

备注

  • 我知道通常建议使方法返回尽可能的最通用类型(此中的 List情况),但我更喜欢将 getter 的返回类型声明为 ImmutableList,因为它充当文档(无需在 Javadoc 中记录返回列表的不变性)和 API 契约。这就像说“我保证这个列表是不可变的,你不必担心或防御性地复制它”。而且非常简洁。
  • ImmutableList.copyOf() 很棒,因为它会自动拒绝空列表(通过抛出 NullPointerException)。它还拒绝空元素。如果源列表已经是 ImmutableList,它不会复制源列表,这避免了无用的对象实例化。
  • 在第二个示例中,我使用 ImmutableList.of() 将字段初始化为空 ImmutableList,因为返回空集合而不是 null 值是一个很好的做法 (空对象模式)。您可能认为这会创建不必要的对象实例化,但 ImmutableList.of() 实际上返回一个单例。

You could also use Google Guava's immutable collections. In this case, you would store an ImmutableList in your field.

Of course, if your class needs to modify this list internally, using ImmutableList might turn out to be a bad idea, since you'll need to create a new ImmutableList instance and reassign it to the field each time...

But it's perfect when you know the List won't change after object construction.

Immutable example (list won't change after object construction)

@Immutable
public final class Foo {

    @Nonnull
    private final ImmutableList<String> list;

    public Foo(@Nonnull List<String> list) {
        // you could also compute the appropriate list here
        // before assigning it to the field
        this.list = ImmutableList.copyOf(list);
    }


    public ImmutableList<String> getList() {
        return list;
    }
}

Mutable example (list may only be modified using the setter)

public class Foo {

    @Nonnull
    private ImmutableList<String> list = ImmutableList.of();

    public ImmutableList<String> getList() {
        return list;
    }

    public void setList(@Nonnull List<String> list) {
        this.list = ImmutableList.copyOf(list);
    }
}

Remarks

  • I know it's often advised to make methods return the most generic type possible (List in this case), but I prefer to declare my getter's return type as an ImmutableList, because it acts as documentation (no need to document the returned list's immutability in the Javadoc) and as an API contract. It's like saying "I guarantee this list to be immutable, you do not have to worry or defensively copy it". And it is very concise.
  • ImmutableList.copyOf() is great, since it automatically rejects null lists (by throwing NullPointerException). It also rejects null elements. And it won't copy the source list if it's already an ImmutableList, which avoids useless object instantiation.
  • In the second example, I initialize the field to an empty ImmutableList using ImmutableList.of(), because it's a good practice to return empty collections instead of null values (Null Object pattern). You might think that this creates needless object instantiation, but ImmutableList.of() actually returns a singleton.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文