1. ホーム
  2. java

[解決済み] Java Enum定義

2022-04-23 05:11:14

質問

Java のジェネリックをかなり理解しているつもりでしたが、java.lang.Enum で次のようなことに遭遇しました。

class Enum<E extends Enum<E>>

この型パラメータをどう解釈すればいいか、どなたか説明してください。似たような型パラメータが使われる他の例を示してくれたらボーナスポイントです。

どのように解決するのですか?

enumの型引数は、同じ型引数を持つenumから派生する必要があることを意味します。どうすればいいのでしょうか?型引数を新しい型そのものにすることです。つまり、StatusCodeというenumがあれば、それと等価である。

public class StatusCode extends Enum<StatusCode>

ここで、制約を確認すると Enum<StatusCode> - それで E=StatusCode . 確認してみましょう。 E 拡張 Enum<StatusCode> ? Yes! 大丈夫です

これのどこがいいんだ、と思われるかもしれませんね :) これはEnumのAPIが自分自身を参照できることを意味します。 Enum<E> を実装しています。 Comparable<E> . ベースクラスは(列挙型の場合)比較を行うことができますが、正しい種類の列挙型同士しか比較しないことを確認することができます。(編集: まあ、ほぼね。一番下の編集を参照)。

私は、ProtocolBuffersのC#移植版で似たようなものを使っています。メッセージ(immutable)とビルダー(mutable, メッセージを構築するために使用)があり、これらはタイプのペアとして提供されます。関係するインターフェースは以下の通りです。

public interface IBuilder<TMessage, TBuilder>
  where TMessage : IMessage<TMessage, TBuilder> 
  where TBuilder : IBuilder<TMessage, TBuilder>

public interface IMessage<TMessage, TBuilder>
  where TMessage : IMessage<TMessage, TBuilder> 
  where TBuilder : IBuilder<TMessage, TBuilder>

つまり、メッセージから適切なビルダーを得ることができ(例えば、メッセージのコピーを取り、いくつかの部分を変更する)、ビルダーから、それを構築し終えたときに適切なメッセージを得ることができる。しかし、APIのユーザがこれを実際に気にする必要がないのは良いことです。これは恐ろしく複雑で、現在の状態になるまでに何度も繰り返されました。

EDIT: これは、それ自体は問題ないが、同じ型ではない型引数を使用する奇妙な型を作成することを止めるものではないことに注意してください。この目的は から保護するというよりも、むしろ 間違った の場合です。

だから、もし Enum がJavaで特別に扱われていない場合、(コメントにあるように)以下のような型を作成することができます。

public class First extends Enum<First> {}
public class Second extends Enum<First> {}

Second を実装します。 Comparable<First> よりも Comparable<Second> しかし First を使用することができます。