简体   繁体   English

Java:是枚举数组的最终引用吗?

[英]Java: is a final reference to an array of enums immutable?

I think that a final reference to an array of enums should be immutable. 我认为对枚举数组的最终引用应该是不可变的。

The uniqueness and singularity of enums is enforced by the JVM, so I believe it is safe to say that they are immutable. 枚举的唯一性和单一性由JVM强制执行,因此我认为可以说它们是不可变的。

A final reference cannot be changed, so the reference is immutable. 最终引用不能更改,因此引用是不可变的。

But ... what about the array? 但是......阵列怎么样? Might it still be possible to subvert the array that contains the enum references? 可能仍有可能破坏包含枚举引用的数组吗?

I have a list of enums that correspond to database columns. 我有一个与数据库列对应的枚举列表。 These column names and their associated data do not change, so ... I would like to have the list as a class variable like so: 这些列名称及其相关数据不会更改,因此...我希望将列表作为类变量,如下所示:

static final List<MetaData<Client>> C_COLUMNS =
        DataTables.CLIENTS.getTableColumnsAsEnums();

where CLIENTS is the DataTable enum for which a list of column enums is being generated. 其中CLIENTS是DataTable枚举,为其生成列枚举列表。 The method that does this follows: 执行此操作的方法如下:

public <T extends DB> List<MetaData<T>> getTableColumnsAsEnums() {
    Class<? extends MetaData> cls = this.columnsEnumToken();
    return new ArrayList(Arrays.<MetaData<T>>asList(cls.getEnumConstants())); }

Am I right? 我对吗? This ought to become part of a multi-threaded design, and so I am concerned about the way that making this critical list of static data would render by app very vulnerable ... if it actually were mutable. 这应该成为多线程设计的一部分,所以我担心这个关键的静态数据列表会被应用程序非常脆弱地呈现的方式......如果它实际上是可变的。

But ... what about the array? 但是......阵列怎么样? Might it still be possible to subvert the array that contains the enum references? 可能仍有可能破坏包含枚举引用的数组吗?

Yes. 是。 All arrays in Java are mutable, irrespective of how you declare the variable that holds the reference to the array. Java中的所有数组都是可变的,无论您如何声明保存对数组的引用的变量。

If you want to avoid this "risk", then you must not expose the array; 如果你想避免这种“风险”,那么你不能暴露数组; ie you need to declare it as private . 即你需要声明它是private You could then do one (or more) of the following: 然后,您可以执行以下一项(或多项)操作:

  • Define a static method that will create and return a copy of the array. 定义一个静态方法,该方法将创建并返回该数组的副本。 (Probably not the best option here ...) (可能不是这里最好的选择...)

  • Define a static get(int) method that returns the ith element of the array. 定义一个返回数组的第i个元素的静态get(int)方法。

  • Wrap the array in a list (using Arrays.asList ) and create an unmodifiable wrapper for it (using Collections.unmodifiableList ). 将数组包装在一个列表中(使用Arrays.asList )并为其创建一个不可修改的包装器(使用Collections.unmodifiableList )。

If you want to get the public <T extends DB> List<MetaData<T>> getTableColumnsAsEnums() to return an immutable List you need to use Collections.unmodifiableList() 如果你想public <T extends DB> List<MetaData<T>> getTableColumnsAsEnums()来返回一个不可变的List你需要使用Collections.unmodifiableList()

Also when you are using an unmodifiable list you don't have to worry about the internal array because the toArray method will return an copy of the internal array, not a reference to the internal array itself. 此外,当您使用不可修改的列表时,您不必担心内部数组,因为toArray方法将返回内部数组的副本,而不是对内部数组本身的引用。 This is true for all the Collections. 对于所有集合都是如此。

The REFERENCE is immutable, the content of that reference is not, that's just how things work. REFERENCE是不可变的,该引用的内容不是,这就是事情的运作方式。
So the following won't work 所以以下方法不起作用

public enum TheEnum {
//......
}

final TheEnum[] arr = new TheEnum[5];
var = new TheEnum[6];

but this will work 但这会奏效

public enum TheEnum {
  OPTION_ONE;
//......
}

final TheEnum[] arr = new TheEnum[5];
var[1] = TheEnum.OPTION_ONE;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM