Java:EnumSet.copyOf - 还有改进的余地吗?

时间:2015-09-22 17:07:07

标签: api javac enumset

我需要从Set中创建EnumSet。我决定使用EnumSet#copyOf方法。但是,由于对此方法的限制:

the specified collection must contain at least one element (in order to determine the new enum set's element type)

我需要确保集合不为空。然后代码变为:

enum Color {RED, GREEN, BLUE}; Set<Color> set = ... // get it from somewhere if (set.isEmpty()) { return EnumSet.noneOf(Color.class); else return EnumSet.copyOf(set);

也许javac确实存在一个真正的限制,以确定传递给copyOf方法的集合成员的正确类型,但是我无法克服这种感觉,我必须求助于上面的事情以迎合空集。这是我的问题:

  1. 这里无法接受空集合的限制是什么?

  2. copyOf(Collection<Enum<E>>)这样的方法签名是否解决了这个问题?

  3. 如果是,它会产生哪些其他问题?

2 个答案:

答案 0 :(得分:0)

查看EnumSet的源代码,我发现需要copyOf(Collection)至少一个元素的两个原因:

  • 检查enum类的可能enum值的数量。此数字用于确定使用的实现:RegularEnumSet使用单个long中的位标记包含的元素(允许最多64个值),JumboEnumSet使用{{1} (long[]数组)。
  • 存储元素的类型并将其用于运行时类型检查(例如,子类调用long中的add(E)方法可以抛出EnumSet.typeCheck(E))。由于类型擦除,这似乎是必要的。
  

ClassCastException这样的方法签名是否已经解决了   这个问题?

签名已基本符合您的建议,只是语法不同:

copyOf(Collection<Enum<E>>)

此处public static <E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c) 定义为E,这意味着<E extends Enum<E>>Collection<E>的某种类型。

答案 1 :(得分:0)

根据EnumSet.copyOf empty collection throws IllegalArgumentException,似乎有用的是复制构造函数,该构造函数接受元素类型参数,这在创建新的EnumSet时是必需的:

 <!--uses-permission android:name="android.permission.SEND_SMS" /-->
    <uses-permission android:name="android.permission.INTERNET" />
    <!--uses-permission android:name="android.permission.CALL_PHONE" /-->
    <!--tools:node="remove"-->


    <uses-feature
        android:name="android.hardware.telephony"
        android:required="false" />

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        tools:ignore="GoogleAppIndexingWarning">
        <service
            android:name="com.premar.radiomunabuddu.RadioMediaPlayerService"
            android:enabled="true" >

        </service>

        <receiver android:name="com.premar.radiomunabuddu.IntentReceiver">
            <intent-filter>
                <action android:name="android.media.AUDIO_BECOMING_NOISY" />
            </intent-filter>
        </receiver>

        <activity
            android:name="com.premar.radiomunabuddu.HomeActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.premar.radiomunabuddu.AboutActivity">
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="com.premar.radiomunabuddu.HomeActivity" />
        </activity>
    </application>

虽然节省的费用很少,但清晰度却很可观。对比:

EnumSet(Class<E>elementType, Enum<?>[] universe)

public static <E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c, Class<E> elementType);

意图只是将给定集合复制为EnumSet。简单,直接地表达这种意图似乎是最合适的。