rawタイプとは何ですか?なぜ使用しないのですか?


662

質問:

  • Javaのraw型とは何ですか?なぜそれらが新しいコードで使用されるべきではないとしばしば聞かれるのですか?
  • 生の型を使用できない場合の代替策は何ですか?

Javaチュートリアルでは、この警告の原因となるJComboBoxがまだ使用されています。この警告が発生しないコンボボックスのバージョンはどれですか?docs.oracle.com/javase/tutorial/uiswing/components/...
スーパースター

1
raw型が存在する理由は、ジェネリックがまったくなかったJava 1.4以前との下位互換性のためです。
Jesper

回答:


744

生タイプとは何ですか?

Java言語仕様では、raw型を次のように定義しています。

JLS 4.8 Rawタイプ

rawタイプは次のいずれかとして定義されます。

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

  • 要素型がraw型である配列型。

  • のスーパークラスまたはスーパーインターフェースから継承されていないstatic未加工の型の非メンバー型。RR

以下に例を示します。

public class MyType<E> {
    class Inner { }
    static class Nested { }

    public static void main(String[] args) {
        MyType mt;          // warning: MyType is a raw type
        MyType.Inner inn;   // warning: MyType.Inner is a raw type

        MyType.Nested nest; // no warning: not parameterized type
        MyType<Object> mt1; // no warning: type parameter given
        MyType<?> mt2;      // no warning: type parameter given (wildcard OK!)
    }
}

これMyType<E>は、パラメータ化されたタイプJLS 4.5)です。このタイプを単にMyType略して口語的に呼ぶことは一般的ですが、技術的には名前はMyType<E>です。

mt上記の定義の最初の箇条書きによる生の型(およびコンパイル警告を生成)。innまた、3番目の箇条書きでrawタイプがあります。

MyType.Nestedはパラメーター化された型のメンバー型ですが、パラメーター化された型MyType<E>ではありませんstatic

mt1、およびmt2どちらも実際の型パラメーターで宣言されているため、生の型ではありません。


rawタイプの何がそれほど特別なのですか?

基本的に、raw型はジェネリックが導入される前と同じように動作します。つまり、以下はコンパイル時に完全に合法です。

List names = new ArrayList(); // warning: raw type!
names.add("John");
names.add("Mary");
names.add(Boolean.FALSE); // not a compilation error!

上記のコードは問題なく実行されますが、次のコードもあるとします。

for (Object o : names) {
    String name = (String) o;
    System.out.println(name);
} // throws ClassCastException!
  //    java.lang.Boolean cannot be cast to java.lang.String

実行namesできない問題が発生したのは、以外のものが含まれているためinstanceof Stringです。

あなたがしたい場合はおそらく、names唯一含むようにString、あなたは可能性があり、おそらく、まだ生の型を使用して、手動ですべてのチェック addを自分で、その後、手動でキャストStringのすべてのアイテムnamesさらに良いのは、生の型を使用せず、 Javaジェネリックの力を利用してコンパイラーにすべての作業を任せることです

List<String> names = new ArrayList<String>();
names.add("John");
names.add("Mary");
names.add(Boolean.FALSE); // compilation error!

もちろん、あなたがあればDOたいnamesできるようにBoolean、あなたのようにそれを宣言することができList<Object> names、そして上記のコードはコンパイルします。

こちらもご覧ください


生の型<Object>は型パラメーターとして使用する場合とどう違うのですか?

以下は、Effective Java 2nd Edition、Item 23:Do n't use raw types in new code

rawタイプListとパラメーター化されたタイプの違いは何List<Object>ですか?大まかに言えば、前者はジェネリック型チェックをオプトアウトしましたが、後者はコンパイラにあらゆる型のオブジェクトを保持できることを明示的に伝えました。あなたが渡すことができますがList<String>種類のパラメータにListは、タイプのパラメータにそれを渡すことはできませんList<Object>。ジェネリックスにはサブタイプ規則がありList<String>、生の型のサブタイプですListが、パラメーター化された型のサブタイプではありませんList<Object>。結果として、のようなraw型を使用する場合は型の安全性が失われListますが、のようなパラメーター化された型を使用する場合は失われませんList<Object>

ポイントを説明するために、を取り、List<Object>を追加する次のメソッドを考えますnew Object()

void appendNewObject(List<Object> list) {
   list.add(new Object());
}

Javaのジェネリックスは不変です。A List<String>はでないList<Object>ため、次の場合はコンパイラ警告が生成されます。

List<String> names = new ArrayList<String>();
appendNewObject(names); // compilation error!

appendNewObject生の型Listをパラメーターとして取るように宣言した場合、これはコンパイルされ、ジェネリックから得られる型の安全性が失われます。

こちらもご覧ください


生の型<?>は、型パラメーターとして使用する場合とどのように異なりますか?

List<Object>List<String>などが全てですList<?>、ちょうど彼らがちょうどだと言って誘惑することができるので、List代わりに。ただし、大きな違いがありますList<E>。aはのみを定義するため、add(E)任意のオブジェクトだけをに追加することはできませんList<?>。一方、raw型にListは型の安全性がないため、addほぼ何でもにできますList

前のスニペットの次のバリエーションを検討してください。

static void appendNewObject(List<?> list) {
    list.add(new Object()); // compilation error!
}
//...

List<String> names = new ArrayList<String>();
appendNewObject(names); // this part is fine!

コンパイラーは、List<?>!の型の不変性に違反する可能性からユーザーを保護するというすばらしい仕事をしました。パラメータをraw型として宣言した場合List list、コードはコンパイルされ、の型不変に違反しますList<String> names


rawタイプはそのタイプの消去です

JLS 4.8に戻る:

型として、パラメーター化された型の消去、または要素型がパラメーター化された型である配列型の消去を使用できます。このような型は、raw型と呼ばれます。

[...]

生の型のスーパークラス(それぞれ、スーパーインターフェイス)は、ジェネリック型のパラメーター化のスーパークラス(スーパーインターフェイス)の消去です。

スーパークラスまたはスーパーインターフェースから継承されていないstaticraw型のコンストラクター、インスタンスメソッド、または非フィールドのC型は、に対応するジェネリック宣言でその型の消去に対応するraw型ですC

簡単に言うと、生の型が使用されると、コンストラクター、インスタンスメソッド、および非staticフィールドも消去されます。

次の例を見てください。

class MyType<E> {
    List<String> getNames() {
        return Arrays.asList("John", "Mary");
    }

    public static void main(String[] args) {
        MyType rawType = new MyType();
        // unchecked warning!
        // required: List<String> found: List
        List<String> names = rawType.getNames();
        // compilation error!
        // incompatible types: Object cannot be converted to String
        for (String str : rawType.getNames())
            System.out.print(str);
    }
}

rawを使用するとMyTypegetNames同様に消去され、rawが返されますList

JLS 4.6は引き続き次のことを説明します。

型消去は、コンストラクターまたはメソッドのシグニチャーを、パラメーター化された型または型変数を持たないシグニチャーにマップします。コンストラクターまたはメソッドシグネチャの消去はs、と同じ名前とsで指定されたすべての仮パラメータータイプの消去で構成されるシグネチャですs

メソッドまたはコンストラクターのシグニチャーが消去されると、メソッドの戻りタイプおよびジェネリックメソッドまたはコンストラクターのタイプパラメーターも消去されます。

ジェネリックメソッドのシグネチャの消去には、型パラメーターはありません。

:なぜ行動のこの種が発生するはずで、次のバグレポートは、マウリツィオCimadamore、コンパイラDEV、とアレックス・バックリー、JLSの著者の一人から、いくつかの考えが含まれていますhttps://bugs.openjdk.java.net/browse / JDK-6400189。(つまり、仕様が単純になります。)


安全でない場合、なぜ生の型を使用できるのですか?

JLS 4.8からの別の引用は次のとおりです。

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

効果的なJava 2nd Editionには、これを追加する機能もあります。

生の型を使用するべきではないのに、なぜ言語デザイナーはそれらを許可したのですか?互換性を提供するため。

Javaプラットフォームは、ジェネリックが導入されてから20年を迎えようとしており、ジェネリックを使用しない膨大な量のJavaコードが存在していました。このすべてのコードが合法であり、ジェネリックを使用する新しいコードと相互運用可能であることが重要であると見なされました。パラメータ化された型のインスタンスを、通常の型で使用するように設計されたメソッドに渡すこと、およびその逆も可能です。移行の互換性と呼ばれるこの要件により、rawタイプをサポートする決定が下されました。

要約すると、生の型は決して新しいコードで使用すべきではありません。常にパラメータ化された型を使用する必要があります


例外はありませんか?

残念ながら、Javaジェネリックは具体化されていないため、新しいコードでraw型を使用する必要がある例外が2つあります。

  • クラスリテラル、例えばList.class、ないList<String>.class
  • instanceofオペランド、例えばo instanceof Set、ないo instanceof Set<String>

こちらもご覧ください


16
「Javaジェネリックは具体化されていない」とはどういう意味ですか?
Carl G

7
2番目の例外についてはo instanceof Set<?>、生の型を回避する構文も許可されています(この場合は表面的なものです)。
Paul Bellora 2013年

1
生の型は非常に便利であり、インターフェースを拡張するBeanのJNDIルックアップの場合にボイラープレートコードを削減します。これによりn、同じコードを持つ実装クラスごとにリモートBean を作成する必要がなくなります。
djmj 14

8
「非具体化」は、それらが消去されたという別の言い方です。コンパイラーは汎用パラメーターが何であるかを認識していますが、その情報は生成されたバイトコードには渡されません。JLSでは、クラスリテラルに型パラメーターがないことが必要です。
エリックG.ハグストロム2015

2
@OldCurmudgeon面白いですね。つまり、クラスリテラルがとして定義されているため、正式にはどちらでもありませんTypeName.class。ここTypeNameで、は単純な識別子(jls)です。仮に言えば、それは本当にどちらかと言えます。多分手がかりとして、List<String>.classJLSが特にコンパイラエラーを呼び出すバリアントであるため、言語に追加した場合、それが使用する言語であると私は予想します。
Radiodef

62

Javaのraw型とは何ですか?なぜそれらが新しいコードで使用されるべきではないとしばしば聞かれるのですか?

Raw型はJava言語の古代の歴史です。初めはありましたCollections、そして彼らはObjectsそれ以上何も持っていませんでした。CollectionsからObject目的の型への必要なキャストに対するすべての操作。

List aList = new ArrayList();
String s = "Hello World!";
aList.add(s);
String c = (String)aList.get(0);

これはほとんどの場合機能しましたが、エラーが発生しました

List aNumberList = new ArrayList();
String one = "1";//Number one
aNumberList.add(one);
Integer iOne = (Integer)aNumberList.get(0);//Insert ClassCastException here

古いタイプレスコレクションはタイプセーフを適用できなかったため、プログラマはコレクション内に何を格納したかを覚える必要がありました。
ジェネリックスはこの制限を回避するために発明されたため、開発者は格納された型を1回宣言し、コンパイラは代わりにそれを行います。

List<String> aNumberList = new ArrayList<String>();
aNumberList.add("one");
Integer iOne = aNumberList.get(0);//Compile time error
String sOne = aNumberList.get(0);//works fine

比較のため:

// Old style collections now known as raw types
List aList = new ArrayList(); //Could contain anything
// New style collections with Generics
List<String> aList = new ArrayList<String>(); //Contains only Strings

Compareableインターフェースをより複雑に:

//raw, not type save can compare with Other classes
class MyCompareAble implements CompareAble
{
   int id;
   public int compareTo(Object other)
   {return this.id - ((MyCompareAble)other).id;}
}
//Generic
class MyCompareAble implements CompareAble<MyCompareAble>
{
   int id;
   public int compareTo(MyCompareAble other)
   {return this.id - other.id;}
}

生の型でCompareAbleインターフェイスを実装することは不可能であることに注意してくださいcompareTo(MyCompareAble)。それらを使用すべきでない理由:

  • Object保存されてCollectionいるものは、使用する前にキャストする必要があります
  • ジェネリックを使用すると、コンパイル時のチェックが可能になります
  • 生の型を使用することは、各値を Object

コンパイラの機能:ジェネリックスは下位互換性があり、生の型と同じJavaクラスを使用します。魔法は主にコンパイル時に発生します。

List<String> someStrings = new ArrayList<String>();
someStrings.add("one");
String one = someStrings.get(0);

次のようにコンパイルされます:

List someStrings = new ArrayList();
someStrings.add("one"); 
String one = (String)someStrings.get(0);

これは、生の型を直接使用した場合と同じコードです。思想私は何が起こるかわからないんだけどCompareAbleインターフェース、私はそれが2つの作成していることを推測compareTo1を取って、機能をMyCompareAble、その他の撮影をAN Objectし、それを鋳造後最初にそれを渡します。

生の型に代わるものは何ですか:ジェネリックを使用してください


30

raw型は、型引数のないジェネリッククラスまたはインターフェースの名前です。たとえば、一般的なBoxクラスが与えられた場合:

public class Box<T> {
    public void set(T t) { /* ... */ }
    // ...
}

のパラメーター化された型を作成するにBox<T>は、仮型パラメーターの実際の型引数を指定しますT

Box<Integer> intBox = new Box<>();

実際の型引数を省略した場合は、次のような生の型を作成しますBox<T>

Box rawBox = new Box();

したがって、Boxはジェネリック型のraw型ですBox<T>。ただし、非ジェネリッククラスまたはインターフェイス型はraw型ではありません。

多くのAPIクラス(Collectionsクラスなど)はJDK 5.0より前のジェネリックではなかったため、生の型はレガシーコードに表示されます。rawタイプを使用すると、基本的にジェネリック前の動作がBox得られます-a はObjects を提供します。下位互換性のために、パラメーター化された型をraw型に割り当てることができます。

Box<String> stringBox = new Box<>();
Box rawBox = stringBox;               // OK

ただし、生の型をパラメーター化された型に割り当てると、警告が表示されます。

Box rawBox = new Box();           // rawBox is a raw type of Box<T>
Box<Integer> intBox = rawBox;     // warning: unchecked conversion

また、raw型を使用して、対応するジェネリック型で定義されたジェネリックメソッドを呼び出すと、警告が表示されます。

Box<String> stringBox = new Box<>();
Box rawBox = stringBox;
rawBox.set(8);  // warning: unchecked invocation to set(T)

警告は、生の型がジェネリック型チェックをバイパスし、安全でないコードのキャッチをランタイムに延期することを示しています。したがって、生の型の使用は避けてください。

Type Erasureセクションには、Javaコンパイラがraw型を使用する方法に関する詳細情報があります。

未チェックのエラーメッセージ

前述のように、レガシーコードとジェネリックコードを混在させると、次のような警告メッセージが表示される場合があります。

注:Example.javaは、チェックされていない、または安全でない操作を使用します。

注:詳細については、-Xlint:uncheckedを指定して再コンパイルしてください。

これは、次の例に示すように、raw型を操作する古いAPIを使用している場合に発生する可能性があります。

public class WarningDemo {
    public static void main(String[] args){
        Box<Integer> bi;
        bi = createBox();
    }

    static Box createBox(){
        return new Box();
    }
}

「チェックされていない」という用語は、型の安全性を確保するために必要なすべての型チェックを実行するのに十分な型情報がコンパイラにないことを意味します。「チェックされていない」警告はデフォルトで無効になっていますが、コンパイラからヒントが得られます。「チェックされていない」警告をすべて表示するには、-Xlint:uncheckedを指定して再コンパイルします。

前の例を-Xlint:uncheckedで再コンパイルすると、次の追加情報が表示されます。

WarningDemo.java:4: warning: [unchecked] unchecked conversion
found   : Box
required: Box<java.lang.Integer>
        bi = createBox();
                      ^
1 warning

未チェックの警告を完全に無効にするには、-Xlint:-uncheckedフラグを使用します。@SuppressWarnings("unchecked")注釈は、未チェックの警告を抑制します。@SuppressWarnings構文に慣れていない場合は、注釈を参照してください。

元のソース:Javaチュートリアル


21

Javaの「raw」型は、ジェネリックではなく、タイプセーフなジェネリック型パラメーターではなく「raw」オブジェクトを処理するクラスです。

たとえば、Javaジェネリックが利用可能になる前は、次のようなコレクションクラスを使用します。

LinkedList list = new LinkedList();
list.add(new MyObject());
MyObject myObject = (MyObject)list.get(0);

オブジェクトをリストに追加するとき、オブジェクトのタイプは関係ありません。リストからオブジェクトを取得するときは、期待するタイプに明示的にキャストする必要があります。

リストに入れることができるオブジェクトのタイプを明示的に指定する必要があるため、ジェネリックスを使用して、「不明な」要素を削除します。

LinkedList<MyObject> list = new LinkedList<MyObject>();
list.add(new MyObject());
MyObject myObject = list.get(0);

ジェネリックでは、get呼び出しからのオブジェクトをキャストする必要がないことに注意してください。コレクションは、MyObjectでのみ機能するように事前定義されています。これこそがジェネリック医薬品の主な原動力です。ランタイムエラーの原因を、コンパイル時にチェックできるものに変更します。


3
より具体的には、生の型は、ジェネリック型の型パラメーターを単に省略したときに得られるものです。RAW型は、実際にはこれまでの下位互換性機能にすぎず、削除される可能性があります。同様の動作は?を使用して取得できます。ワイルドカードパラメータ。
John Flatness

@zerocrates:類似していますが異なります!?まだ使用するとタイプセーフティが提供されます。私はそれを私の答えでカバーしました。
polygenelubricants

19
 private static List<String> list = new ArrayList<String>();

type-parameterを指定する必要があります。

警告は、ジェネリックをサポートするように定義されている型は、生の形式を使用するのではなく、パラメーター化する必要があることを示しています。

Listジェネリックをサポートするように定義されていpublic class List<E>ます:。これにより、コンパイル時にチェックされる多くのタイプセーフな操作が可能になります。


3
Java 7でダイヤモンド推論に置き換えられましたprivate static List<String> list = new ArrayList<>();
Ian Campbell

14

rawタイプとは何ですか?なぜそれらが新しいコードで使用されるべきではないとしばしば聞かれるのですか?

「生の型」とは、パラメータ化された型の型引数を指定せずにジェネリッククラスを使用するListことですList<String>。たとえば、の代わりに使用します。ジェネリックがJavaに導入されたとき、ジェネリックを使用するようにいくつかのクラスが更新されました。これらのクラスを(生の型)として(型引数を指定せずに)使用すると、レガシーコードをコンパイルできます。

「Rawタイプ」は、下位互換性のために使用されます。type引数を指定したジェネリッククラスを使用すると、より強力な型指定が可能になるため、新しいコードでの使用はお勧めできません。これにより、コードの理解しやすさが向上し、潜在的な問題を早期に発見できる場合があります。

生の型を使用できない場合の代替策は何ですか?

推奨される代替策は、適切な型引数(などList<String>)を使用して、意図したとおりにジェネリッククラスを使用することです。これにより、プログラマーはタイプをより具体的に指定でき、変数またはデータ構造の使用目的について将来のメンテナーにより多くの意味を伝え、コンパイラーはより優れたタイプセーフを実施できます。これらの利点により、コードの品質が向上し、コーディングエラーの発生を防ぐことができます。

たとえば、プログラマが 'names'という名前のList変数に文字列のみが含まれていることを確認するメソッドの場合:

List<String> names = new ArrayList<String>();
names.add("John");          // OK
names.add(new Integer(1));  // compile error

1
ああ、スタックオーバーフロー.com / questions / 2770111 /… polygenelubricantsからの「生の型」参照を自分の回答にコピーしたくなったのですが、自分の回答で使用するために残しておきます。
バートF

1
はい、私は本質的に、人々がスタックオーバーフローで生の型を使用するすべての場所でそのセグメントをコピーして貼り付けており、最後に参照する質問を1つだけにすることにしました。コミュニティにとって良い貢献になることを願っています。
polygenelubricants

1
@polygenelubricants私が気づいた-私たちは同じ質問のいくつかにぶつかった:-)
Bert F

1
@ ha9u63ar:確かに。一般に、簡潔で単純な回答は、長く受け入れられている回答と少なくとも同じくらい優れています。
displayName

「強力なサイピング」とは何ですか?
carloswm85

12

コンパイラはあなたにこれを書くことを望みます:

private static List<String> list = new ArrayList<String>();

それ以外の場合は、好きなタイプをに追加しlistて、インスタンス化をnew ArrayList<String>()無意味なものにすることができます。Javaジェネリックはコンパイル時の機能のみであるため、「生の型」の参照に割り当てられている場合、で作成されたオブジェクトは要素または要素new ArrayList<String>()を喜んで受け入れます。オブジェクト自体は、どの型を含むかについて何も知らず、コンパイラのみが認識します。IntegerJFrameList


12

ここで、コンセプトを明確にできる複数のケースを検討しています

1. ArrayList<String> arr = new ArrayList<String>();
2. ArrayList<String> arr = new ArrayList();
3. ArrayList arr = new ArrayList<String>();

事例1

ArrayList<String> arrそれはArrayList型の参照変数Stringに参照ArralyList型のオブジェクトString。つまり、String型のオブジェクトのみを保持できます。

StringRawタイプではないので厳密であり、警告を発することはありません。

    arr.add("hello");// alone statement will compile successfully and no warning.

    arr.add(23);  //prone to compile time error.
     //error: no suitable method found for add(int)

事例2

この場合ArrayList<String> arrは厳密な型ですが、オブジェクトnew ArrayList();は生の型です。

    arr.add("hello"); //alone this compile but raise the warning.
    arr.add(23);  //again prone to compile time error.
    //error: no suitable method found for add(int)

こちらarrはStrictタイプです。したがって、を追加すると、コンパイル時エラーが発生しますinteger

警告:- Rawタイプオブジェクトは、Strictタイプの参照変数に参照されていArrayListます。

事例3

この場合ArrayList arrはrawタイプですが、オブジェクトnew ArrayList<String>();はStrictタイプです。

    arr.add("hello");  
    arr.add(23);  //compiles fine but raise the warning.

arrRawタイプであるため、任意のタイプのオブジェクトが追加されます。

警告:- Strictタイプオブジェクトは、rawタイプ参照変数に参照されています。


8

型は、の欠如であるtypeパラメータジェネリック型を使用しました。

rawタイプは、sのdoublea Setであると想定されていたものにa を挿入するなどのランタイムエラーを引き起こす可能性があるため、使用しないでくださいint

Set set = new HashSet();
set.add(3.45); //ok

からのものを取得するとき、Set何が出てくるのかわかりません。それがすべてであると想定しint、それをにキャストするとしIntegerます。double3.45が登場する実行時の例外。

ではtypeパラメータあなたに追加しSet、一度にコンパイルエラーが発生します。このプリエンプティブエラーにより、ランタイム中に何かが爆発する前に問題を修正できます(したがって、時間と労力を節約できます)。

Set<Integer> set = new HashSet<Integer>();
set.add(3.45); //NOT ok.

7

生の型があなたを噛む別のケースがあります:

public class StrangeClass<T> {
  @SuppressWarnings("unchecked")
  public <X> X getSomethingElse() {
    return (X)"Testing something else!";
  }

  public static void main(String[] args) {
    final StrangeClass<String> withGeneric    = new StrangeClass<>();
    final StrangeClass         withoutGeneric = new StrangeClass();
    final String               value1,
                               value2;

    // Compiles
    value1 = withGeneric.getSomethingElse();

    // Produces compile error:
    // incompatible types: java.lang.Object cannot be converted to java.lang.String
    value2 = withoutGeneric.getSomethingElse();
  }
}

受け入れられた回答で述べたように、生の型のコード内のジェネリックのサポートはすべて失われます。すべての型パラメーターは、消去(上記の例ではObject)に変換されます。


5

言っていることはあなたlistList特定されていないオブジェクトのことです。つまり、Javaはリスト内にどのようなオブジェクトがあるかを認識していません。次に、リストを反復処理する場合は、すべての要素をキャストして、その要素(この場合は文字列)のプロパティにアクセスできるようにする必要があります。

一般に、コレクションをパラメーター化することをお勧めします。変換の問題は発生せず、パラメーター化された型の要素のみを追加でき、エディターは選択する適切なメソッドを提供します。

private static List<String> list = new ArrayList<String>();

4

チュートリアルページ

raw型は、型引数のないジェネリッククラスまたはインターフェースの名前です。たとえば、一般的なBoxクラスが与えられた場合:

public class Box<T> {
    public void set(T t) { /* ... */ }
    // ...
}

Boxのパラメーター化された型を作成するには、仮型パラメーターTに実際の型引数を指定します。

Box<Integer> intBox = new Box<>();

実際の型引数が省略されている場合は、ボックスの生の型を作成します。

Box rawBox = new Box();

2

生の型を避ける

生の型とは、型パラメーターを指定せずにジェネリック型を使用することを指します。

たとえば

リストは生の型List<String>ですが、パラメーター化された型です。

ジェネリックがJDK 1.5で導入されたとき、生の型は古いバージョンのJavaとの下位互換性を維持するためにのみ保持されていました。rawタイプを使用することも可能ですが、

彼らは避けるべきです

  • 彼らは通常キャストが必要です
  • それらはタイプセーフではなく、いくつかの重要な種類のエラーは実行時にのみ表示されます
  • 彼らはあまり表現力で、パラメータ化された型と同じように自己文書をない

    import java.util.*;
    
    public final class AvoidRawTypes {
    
    void withRawType() {
    
        //Raw List doesn't self-document, 
        //doesn't state explicitly what it can contain
    
        List stars = Arrays.asList("Arcturus", "Vega", "Altair");
    
        Iterator iter = stars.iterator();
    
        while (iter.hasNext()) {
    
            String star = (String) iter.next(); //cast needed
    
            log(star);
        }
    
    }
    
    void withParameterizedType() {
    
        List < String > stars = Arrays.asList("Spica", "Regulus", "Antares");
    
        for (String star: stars) {
    
            log(star);
        }
    
    }
    
    private void log(Object message) {
    
        System.out.println(Objects.toString(message));
    
    }
    
    }

参照用https : //docs.oracle.com/javase/tutorial/java/generics/rawTypes.html


1

このページは、いくつかのサンプル演習を行ってまったく同じ困惑した後に見つかりました。

==============サンプルから提供されたように、このコードから移行しました===============

public static void main(String[] args) throws IOException {

    Map wordMap = new HashMap();
    if (args.length > 0) {
        for (int i = 0; i < args.length; i++) {
            countWord(wordMap, args[i]);
        }
    } else {
        getWordFrequency(System.in, wordMap);
    }
    for (Iterator i = wordMap.entrySet().iterator(); i.hasNext();) {
        Map.Entry entry = (Map.Entry) i.next();
        System.out.println(entry.getKey() + " :\t" + entry.getValue());
    }

======================このコードへ========================

public static void main(String[] args) throws IOException {
    // replace with TreeMap to get them sorted by name
    Map<String, Integer> wordMap = new HashMap<String, Integer>();
    if (args.length > 0) {
        for (int i = 0; i < args.length; i++) {
            countWord(wordMap, args[i]);
        }
    } else {
        getWordFrequency(System.in, wordMap);
    }
    for (Iterator<Entry<String, Integer>> i = wordMap.entrySet().iterator(); i.hasNext();) {
        Entry<String, Integer> entry =   i.next();
        System.out.println(entry.getKey() + " :\t" + entry.getValue());
    }

}

================================================== =============================

安全かもしれませんが、哲学を混乱させるのに4時間かかりました...


0

生の型は、表現したいものを表現するときに問題ありません。

たとえば、逆シリアル化関数はを返す可能性Listがありますが、リストの要素の型はわかりません。だから、Listここでは、適切な戻り値の型があります。


使用できますか?typeパラメータとして
ダニエル・キシュ

はい、しかしそれはタイプすることより多くであり、私はもっとタイプすることに反対です。:)
ステファン・ライヒ2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.