2

次の関数を検討してください。

public static <T> T doSomething(Document doc, String xpath, Class<T> returnType);

アイデアは、XML ドキュメントを処理し、指定された xpath でオブジェクトを取得し、指定された型の何かを返すという単純なものです。ここで、 if をenum 型ではなくreturnType.isEnum()a を取得するかのように扱い、最後に使用するようにしたいとしましょう。StringEnum.valueOf()

残念ながら、

String returnedObj = String.class.cast(...); // Returned value from the actual XPath.evaluate() call
return Enum.valueOf(returnType, returnedObject);

ではないため、機能しませreturnTypeClass<T extends Enum<T>>returnTypeただし、どちらの方法でも実際にそのように形作ることはできませんClass.asSubclass()(少なくとも、回避しようとしている危険なキャストがなければ)。

また、doSomething()列挙型固有のことを行うためにオーバーロードできないようです。

public static <T extends Enum<T>> T doSomething(Document doc, String xpath, Class<T> returnType);

これは文字通り「同じ署名」のランタイムであるためです。

したがって、問題は、これらすべてを 1 つのメソッドで安全に行う方法があるか、または列挙型を特別に処理したり、安全でないキャストに頼ったりする別のメソッドが必要かということです。

4

1 に答える 1

1

私はその問題に十分に興味を持っていたので、試してみました。私は成功しませんでしたが、議論を深めるために、ここでその試みを共有する価値があると思いました.

interface Evaluator {
  <T> T evaluate(String path, Class<? extends T> type);
}


final class Attempt implements Evaluator {
  @Override
  public <T> T evaluate(String path, Class<? extends T> type) {
    final Object result = evaluatePath(path, type);
    return type.cast(type.isEnum() ?
                     valueOf(type.asSubclass(Enum.class), (String)result) :
                     result);
  }


  private static Object evaluatePath(String path, Class<?> type) {
    /* This doesn't actually do anything meaningful, but that doesn't matter for now.
       Presumably it would make a call to something like XPath#evaluate().
     */
    return path;
  }


  private static <T extends Enum<T>> T valueOf(Class<T> type, String name) {
    return Enum.valueOf(type, name);
  }
}

このコードは、IntelliJ IDEA の as-you-type コンパイラーに合格しますが、実際のjavacに送信すると失敗します。

[unchecked] unchecked method invocation:
  <T>valueOf(java.lang.Class<T>,java.lang.String) in Attempt is applied to
  (java.lang.Class<capture#474 of ? extends java.lang.Enum>,java.lang.String)

このエラー メッセージは不可解であり、パラメータ化された型を探すメソッドに生の型Enum( のように)を渡した結果の表現が不十分だと思います。Class<Enum>

ここでどの忌まわしいキャストが必要かを確認するために、必要な変更を示すために上記のコードを編集 (またはコピーして拡張) することを他の人に勧めます。

于 2012-08-29T01:23:01.737 に答える