5

私は愚かすぎてグーグルを使用できないか、これまで誰もこの問題に遭遇していません。

次のコードをコンパイルしようとしています。

public interface MyClass {
  public class Util {
    private static MyClass _this;
    public static <T extends MyClass> T getInstance(Class<T> clazz) {
      if(_this == null) {
        try {
          _this = clazz.newInstance();
        } catch(Exception e) {
          e.printStackTrace();
        }
      }
      return _this;
    }
  }
}

しかし、「return _this;」という行で 「タイプの不一致: MyClass から T に変換できません」というエラーが表示されるのはなぜですか? T は MyClass を拡張するので、どこに問題があるのでしょうか? 行を「return (T)_this;」に変更すると、チェックされていないキャストに関する警告が表示されますが、警告は好きではありません;-) エラーや警告なしで目的を達成する方法はありますか?

4

4 に答える 4

6

、、の2つの実装がMyClassあるFooとしBarます。MyClassタイプのフィールドとして、はまたはである_this可能性がありFooますBar

さて、あなたのgetInstanceメソッドはを返す<T extends MyClass>ので、これらの方法のいずれかでそれを呼び出すことは合法です:

MyClass myClass = Util.getInstance(MyClass.class);

MyClassはインターフェイスであり、でインスタンス化できないため、これが最初の呼び出しの場合は機能しませんnewInstance()

Foo foo = Util.getInstance(Foo.class);
Bar bar = Util.getInstance(Bar.class);

さて、もしあなたが電話をかけ_thisたらどうなるでしょうか?そのため、これを行うことは許可されていません。FooUtil.getInstance(Bar.class)

于 2011-05-31T20:19:59.110 に答える
4

これは、変数_thisが typeMyClassではなく type であるためTです。のインスタンスがたまたま含まれていてもT、コンパイラにはそれを知る方法がありません。

于 2011-05-31T20:10:32.997 に答える
2

これによりコンパイラが満足し、必要な方法で型を制限できることを確認しました。

public interface MyClass {
  public class Util {
    private static MyClass _this;
      public static MyClass getInstance(Class<? extends MyClass> clazz) {
        if(_this == null) {
          try {
            _this = clazz.newInstance();
          } catch(Exception e) {
            e.printStackTrace();
          }
        }
        return _this;
    }
  }
}

編集:

クライアント コードについて考えると、これは実際には、このファクトリの設計のバグを明らかにしているだけです。これを想像してください:

MyClass foo = MyClass.getInstance(Foo.class); // sets _this to a Foo and returns it

MyClass bar = MyClass.getInstance(Bar.class); // _this is already set to a Foo and
                                              // we return a Foo when we probably
                                              // are expecting a Bar!
于 2011-05-31T20:18:11.573 に答える
1

「タイプミスマッチ」…

...次の理由によるものです。

  • Tのサブクラスを表しMyClassます。
  • getInstance型のオブジェクトを返すように宣言されていますT
  • タイプのオブジェクトを返しますMyClass

メソッドが aDoubleを返し、 someを返すように宣言するようなものNumberです。

ソリューション...

... returnステートメントをに変更することです

return (T) _this;

@SuppressWarnings("unchecked")(そして、警告を取り除きたい場合は追加してください)。

しかし、問題があります...

ColinD が指摘するように:

class MyClassImpl1 implements MyClass {
}

class MyClassImpl2 implements MyClass {
}

次の操作を行います。

MyClassImpl1 o1 = MyClass.Util.getInstance(MyClassImpl1.class);
// _this now holds a value of type MyClassImpl1...

// ... which causes this line to throw a ClassCastException.
MyClassImpl2 o2 = MyClass.Util.getInstance(MyClassImpl2.class);
于 2011-05-31T20:16:41.157 に答える