1

コード

  interface BaseIntr<T>{
      void saveSwiftMsg(Collection<String> headers) throws Exception;
  }

 class Impl implements BaseIntr{
       public void saveSwiftMsg(Collection<String> headers) throws Exception { }     
  }

コードの編集バージョン:

  interface BaseIntr<T>{
     T process(T t);
     void saveSwiftMsg(Collection<String> headers)      throws Exception;
  }

  class Impl implements BaseIntr{
     public void saveSwiftMsg(Collection<String> headers) throws Exception {    }
    @Override
    public Object process(Object t) {       return t;   }   
  }

作業環境

Javaバージョン:1.7.0_04、ベンダー:Oracle Corporation

デフォルトのロケール:en_IN、プラットフォームエンコーディング:Cp1252

OS名:「windows7」、バージョン:「6.1」、アーチ:「amd64」、ファミリ:「windows」

Javaコンパイラは次の例外をスローします。しかし、BaseIntrから<T>を削除すると、正常に機能します。

javac gen\GenericsTest.java
gen\GenericsTest.java:18: error: Impl is not abstract and does not override abstract     method saveSwiftMsg(Collection) in BaseIntr
 class Impl implements BaseIntr{
 ^
 gen\GenericsTest.java:20: error: name clash: saveSwiftMsg(Collection<String>) in Impl and saveSwiftMsg(Collection<String>) in BaseIntr have the same erasure, yet neither overrides the other
 public void saveSwiftMsg(Collection<String> headers) throws Exception {
                ^
2 errors
4

3 に答える 3

3

インターフェイスはタイプでパラメータ化Tされています。実装するときは、次のようにタイプを指定する必要があります。

class Impl implements BaseIntr<String>{
}

それはあなたがそれをのために実装したい場合ですString。ただし、パラメータを実装クラスに委任することはできます。

class Impl<T> implements BaseIntr<T>{
}

次に、クラスをインスタンス化するときにタイプを指定する必要があります。

于 2013-03-08T12:27:00.523 に答える
2

型引数(implements BaseIntr)を指定せずにジェネリック型を使用する場合は、raw型を使用します。これらは、Java言語仕様によって次のように定義されています。

非ジェネリックレガシーコードとのインターフェースを容易にするために、パラメーター化された型(§4.5)の消去(§4.6)または要素型がパラメーター化された型である配列型(§10.1)の消去を型として使用することができます。 。このようなタイプは、rawタイプと呼ばれます。

より正確には、rawタイプは次のいずれかとして定義されます。

  • 型引数リストを伴わないジェネリック型宣言の名前をとることによって形成される参照型。

スーパークラスまたはスーパーインターフェースから継承されないrawタイプCのコンストラクター(§8.8)、インスタンスメソッド(§8.4、§9.4)、または非静的フィールド(§8.3)Mのタイプは、対応するrawタイプです。 Cに対応する総称宣言のその型の消去に。

つまり、継承されたメソッドには署名があります

saveSwiftMsg(Collection headers) throws Exception 

オーバーライドするには、オーバーライドするメソッドは、継承されたメソッドと同じシグネチャを持っている必要があります。そうしないと、コンパイルエラーが発生します。

本来の目的(レガシーコードとのインターフェイス)にのみraw型を使用し、対応するコンパイラ警告を有効化(および修正)することを強くお勧めします。

そのことについては、仕様もそうです:

raw型の使用は、レガシーコードの互換性への譲歩としてのみ許可されます。ジェネリックスをJavaプログラミング言語に導入した後に記述されたコードでraw型を使用することは強くお勧めしません。Javaプログラミング言語の将来のバージョンでは、raw型の使用が許可されなくなる可能性があります。

型付け規則の潜在的な違反に常にフラグが立てられるようにするために、raw型のメンバーへのアクセスによっては、コンパイル時にチェックされていない警告が発生します。raw型のメンバーまたはコンストラクターにアクセスするときのコンパイル時のチェックされていない警告の規則は次のとおりです。

  • フィールドへの割り当て時:左側のオペランドの型がraw型の場合、消去によってフィールドの型が変更されると、コンパイル時のチェックされていない警告が発生します。

  • メソッドまたはコンストラクターの呼び出し時:検索するクラスまたはインターフェースのタイプ(§15.12.1)がrawタイプの場合、消去によってメソッドの正式なパラメータータイプのいずれかが変更されると、コンパイル時のチェックされていない警告が発生します。またはコンストラクタ。

そのコンパイラの警告に注意し、実装するインターフェイスのタイプパラメータを指定する必要があります。

于 2013-03-08T12:42:01.560 に答える
1

サブクラスでも指定する必要があります

class Impl implements BaseIntr<T>{
       public void saveSwiftMsg(Collection<String> headers) throws Exception { }     
  }

実際にはタイプを指定する必要があります。

interface BaseIntr<String>{
      void saveSwiftMsg(Collection<String> headers) throws Exception;
  }

 class Impl implements BaseIntr<String>{
           public void saveSwiftMsg(Collection<String> headers) throws Exception { }     
      }
于 2013-03-08T12:25:19.657 に答える