Javaのジェネリックとリフレクション:クラスのロード

cypherman:

私は私には不明であるいくつかのクラスを与えられています。そのうちのいくつかは、一例として示されています。

class Paper {}

class Bakery {}

class Cake extends Bakery {}

class ReflexiveBaker {

  /**
   * Create bakery of the provided class.
   * 
   * @param order class of bakery to create
   * @return bakery object
   */
  public Object bake(Class order) {
    // Add implementation here
  }

}

タスクは、必要に応じてメソッドシグネチャの種類を再設計し、実装を追加することです。ベーク方法は、以下に準拠する必要があります。

  • クラス引数に応じてクラスベーカリーまたはそれの任意のサブクラスのオブジェクトを作成します。
  • 旗コンパイル時エラー(それは紙またはオブジェクトである場合など)order引数は、ベーカリーやそれの任意のサブクラスではない場合

Main.java ::エラー:互換性のない型を:どのような私は、エラーを取得していますしようとしたオブジェクトはケーキケーキケーキに変換することはできません= baker.bake(Cake.class)。

私が思い付くした最高のはこれです:

。公的オブジェクトベーク(クラス順序)は例外{リターンorder.getDeclaredConstructor()のnewInstance()を投げます。

私はそれが間違っていることを知っているが、私は完全にここにこだわっています。誰かが何が起こっているか説明していただけますか?

ラビンドラRanwala:

あなたのメソッドの戻り値の型があるjava.lang.Objectと、コンパイラは、戻り値の型であることを保証することはできませんCakeあなたはこのような明示的なチェックされないキャストを追加することで、コンパイラを説得しない限り。

Cake cake = (Cake) ReflexiveBaker.bake(Cake.class);

このチェックボックスをオフキャストが発生しやすいと厄介なエラーです。あなたがのサブタイプであるパンと呼ばれる別のクラスを持っていると言うBakeryと、あなたは戻り値の型としてケーキを期待して、そのクラスのインスタンスを渡します。上記の文はまだコンパイルしますが、スローClassCastException実行時に。

より良いアプローチは、それが唯一のサブタイプを受け入れるようパラメータバインドタイプを用いる方法generifyするBakery、提供クラスオブジェクトの型パラメータと同じ型を返します。ここではそのような試みです。

static class ReflexiveBaker {
    public static <T extends Bakery> T bake(Class<T> order) {
        try {
            return order.getDeclaredConstructor().newInstance();
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException
                    | InvocationTargetException e) {
            throw new AssertionError("Class could not be instantiated.", e);
        }
    }
}

おすすめ

転載: http://10.200.1.11:23101/article/api/json?id=428506&siteId=1