sun.misc.SharedSecrets的用法

时间:2012-01-31 11:17:56

标签: java

我最近在代码库中找到了这个小宝石。我必须承认,我完全不知道为什么这个枚举是用这种方式编写的(名称改为保护无辜者):

package foo.bar;

import sun.misc.SharedSecrets;
import foo.baz.HasAGetValuesMethod;

public enum MysteryEnum implements HasAGetValuesMethod {

   THINGY, BOB;

   @Override
   public MysteryEnum[] getValues() {
      return SharedSecrets.getJavaLangAccess().getEnumConstantsShared(MysteryEnum .class);
   }
}

在getValues()方法中,而不是简单地调用MysteryEnum.values(),而是使用名为sun.misc.SharedSecret的内容来获取名为sun.misc.JavaLangAccess的句柄,然后使用 获取所有枚举值的数组。该类上的Javadoc告诉你该方法的作用,但我找不到为什么你想要调用它。

写这篇文章的开发者已经不在了,所以我不能问他。无论如何我会问我的团队,但我觉得答案是:“不知道为什么会这样,但最好不要改变它”。目前,我假设这是一个奇怪的情况,有人不知道values()方法存在,或者我对sun.misc库的无知导致我错过了其他人明显的东西。知道这个代码是用这种方式编写的吗?

4 个答案:

答案 0 :(得分:9)

该方法返回相同的数组而不反射或复制/克隆基础数组。这样可以提高性能,但是暴露可变数组并不是一个好主意。

for (int i = 0; i < 3; i++)
    System.out.println(SharedSecrets.getJavaLangAccess().getEnumConstantsShared(AccessMode.class));
AccessMode[] ams = SharedSecrets.getJavaLangAccess().getEnumConstantsShared(AccessMode.class);
ams[1] = ams[2]; // don't do this !!
System.out.println(EnumSet.allOf(AccessMode.class));

打印

[Ljava.nio.file.AccessMode;@330cdec1
[Ljava.nio.file.AccessMode;@330cdec1
[Ljava.nio.file.AccessMode;@330cdec1
[READ, EXECUTE, EXECUTE]

我不是使用这种方法,而是使用自己的缓存副本

// cannot be modified.
private static final AccessMode[] ACCESS_MODES = AccessMode.values();

答案 1 :(得分:4)

基本上SharedSecret

  

“共享秘密”的存储库,它是一种机制       在没有的情况下在另一个包中调用implementation-private方法       使用反射。

代码通过读取类并返回常量来返回枚举常量(无需进行反射调用)。这是动态的,如果将新的枚举常量添加到枚举中,getValues()方法将返回添加的枚举(无需在整个节目中更改代码)。

答案 2 :(得分:1)

documentation说:

  

返回枚举类的元素,如果是Class对象,则返回null   不代表枚举类型;结果是uncloned,cached和shared   所有来电者。

所以,除非要提供一个共享数组,否则任何人都可以通过将其中一个元素设置为null或对其进行排序或其他任何方式来破坏所有内容(可以通过缓存{{{ 1}}方法),我的猜测也是因为前任开发人员的能力不足而存在这条线。

我会写一个单元测试,然后用values()调用替换它,并检查单元测试是否仍然通过。

答案 3 :(得分:0)

仅供参考: 我正在研究EnumMap的实现,并找到了相同的代码段,其中所有枚举值都从类名中获取。

/**
 * Returns all of the values comprising K.
 * The result is uncloned, cached, and shared by all callers.
 */
private static <K extends Enum<K>> K[] getKeyUniverse(Class<K> keyType) {
    return SharedSecrets.getJavaLangAccess()
                                    .getEnumConstantsShared(keyType);
}