4

Wicket 1.3 から Wicket 1.4 への移行で問題が発生していますが、この質問は Java ジェネリック全体にも当てはまります。移行により、どこからともなく何百もの警告が発生しました。Wicket に慣れていない人のために説明すると、多くの Wicket クラスは、v1.4 で一般化された共通の祖先から派生しています。また、どのパラメーターを適用すればよいかわかりません。場合によっては、ほとんどがさまざまなフォームとテーブルです。<?><Object>またはでできると思いますが、どちらか<Void>わかりません。

<?>が最も適しているように思えますが、ワイルドカードを使用できない場所がたくさんあります。 <Object>すべての場合に機能しますが、基本的にワイルドカードを使用せずにワイルドカードを書いているため、不安になります。これは、私の脳の一部にとって本質的に間違っていると感じています。Wicket migration guideで使用<Void>が提案されました。

では、この場合どうするのが適切でしょうか?


編集 2: 私の最初の編集 (現在は質問の一番下にあります) は、文字列のコレクションについて質問しているように見えることで、人々を混乱させたと思います。他の例とその警告を次に示します。

public class DocumentProcessor extends Form implements DocumentManagement { ...

フォームは raw タイプです。ジェネリック型 Form への参照はパラメーター化する必要があります

AjaxFallbackDefaultDataTable theTable = new AjaxFallbackDefaultDataTable("theTable", cols, dataProvider, recPerPg);

この行に複数のマーカー
- 型の安全性: コンストラクター AjaxFallbackDefaultDataTable(String, List, ISortableDataProvider, int) は生の型 AjaxFallbackDefaultDataTable に属します。ジェネリック型 AjaxFallbackDefaultDataTable への参照はパラメーター化する必要があります
- AjaxFallbackDefaultDataTable は生の型です。ジェネリック型 AjaxFallbackDefaultDataTable への参照はパラメーター化する必要があります
- AjaxFallbackDefaultDataTable は生の型です。ジェネリック型 AjaxFallbackDefaultDataTable への参照はパラメーター化する必要があります


編集:サンプルコードを必要としないほど質問を広くしたいと思っていましたが、ここにいくつかあります。

List<IColumn> columns = new ArrayList<IColumn>();
columns.add(new PropertyColumn(new Model<String>("Number"), "revisionID"));

次の警告が生成されます。

[最初の] 行に複数のマーカー
- IColumn は raw タイプです。ジェネリック型 IColumn への参照はパラメーター化する必要があります
- IColumn は生の型です。ジェネリック型 IColumn への参照はパラメーター化する必要があります

[2 番目の] 行に複数のマーカー
- 型の安全性: コンストラクター PropertyColumn(IModel, String) は生の型 PropertyColumn に属します。ジェネリック型 PropertyColumn への参照はパラメーター化する必要があります
- PropertyColumn は生の型です。ジェネリック型 PropertyColumn への参照はパラメーター化する必要があります

エラーはありません。

4

6 に答える 6

1

利用可能な代替手段は次のとおりです。

  1. サンプル コードのように生の型を使用するには、単に警告を無視します。
  2. ワイルドカード/オブジェクト ジェネリックを使用するには
  3. extends ジェネリックを使用するには

あなたの質問から、#1はあなたにとって実行可能な選択肢ではないと推測しています。

#2 の例 (ワイルドカード/オブジェクト)

List<IColumn<?>> columns = new ArrayList<IColumn<?>>();

また

List<IColumn<Object>> columns = new ArrayList<IColumn<Object>>();

?IMOまたはを選択するかどうかは実際には問題ではないと思いますObject。少なくとも機能的には、どちらがより正しいということもありません。
ジェネリックが何であるかを気にせず、それにアクセスしない場合、それは重大な問題です。慎重に検討してください。実際に可能であれば、将来ここでジェネリックを使用します。IColumnこれは、移行前のコードで、オブジェクト内から何も型キャストする必要がないことに気付いた場合にのみ発生する可能性があります。

#3 の例 (ジェネリックを拡張)

型の可能なすべてのジェネリックへのスーパータイプまたは共通インターフェイスを作成しますIColumn。どこで
T extends MyType

List<IColumn<T>> columns = new ArrayList<IColumn<T>>();

2 番目と 3 番目の方法のどちらを選択するかは、IColumn実際に可能な汎用属性に基づいて決定します。

  • それらが独自のクラスであり、実際にジェネリック型のオブジェクトにアクセスしたい場合は、3 番目の方法を使用します。
  • それ以外の場合は、たとえばStringなどのボックス化されたプリミティブをInteger使用するか、ジェネリック型のオブジェクトにアクセスできない場合は、方法 2 を使用します。

HTH

于 2009-12-01T12:41:09.140 に答える
1

意味的には、使用<?>は「タイプがわからない、実際にはまったく気にしないことを意味します。他のものを使用すると、期待されるコンテンツの形式に期待が設定されます。実際に<Object>は、同じことを行いますが、プロパティを使用すると述べています。パラメータ型を使用するジェネリックの。

したがって、経験則は次のようになります。

  • パラメーター化されたコンテンツではなく、遺伝的オブジェクトのみで作業する場合は<?>、パラメーターが動作に関係しないことが一目でわかるように使用します。
  • それ以外の場合は、メソッドが動作するように設計されたすべての型を網羅する最も具体的なパラメーターを使用します。極端な場合は<Object>、その他含む<? extends SomeTopLevelType>
于 2009-12-02T23:47:52.203 に答える
0

コンポーネントに関連付けられたモデルのタイプを使用したい。つまり、getModelObject() の呼び出しによって返される型を使用します。したがって、移行ガイドの例を使用するには:

ListView<Person> peopleListView = new ListView<Person>("people", people) {
    protected void populateItem(ListItem<Person> item) {
        item.add(new Link<Person>("editPerson", item.getModel()){
            public void onClick() {
                Person p = getModelObject();
                setResponsePage(new EditPersonPage(p));
            }
        });
    }
};

ジェネリックを使用すると、それが人物のリストであり、人物をモデルとして使用する編集ページへのリンクがあることが簡単にわかります。残念ながら、Wicket ではコンポーネントにモデルが関連付けられていないことがよくあります。その場合、getModel() は null を返すため、使用する適切な型は です<Void>。これは本質的に null のプレース ホルダーです。

DocumentProcessor

public class DocumentProcessor extends Form implements DocumentManagement { ...

DocumentProcessor のモデルを設定していない場合は、次のようになります。

public class DocumentProcessor extends Form<Void> implements DocumentManagement {
    public DocumentProcessor(String id) {
        super(id);
        ....

ただし、モデル DocumentProcessor を使用すると、次のようになります。

public class DocumentProcessor extends Form<Document> implements DocumentManagement {
    public DocumentProcessor(String id, Document doc) {
        super(id, doc);

AjaxFallbackDefaultDataTable

そのコンストラクターから判断すると、AjaxFallbackDefaultDataTable はそのモデルに IColumn[] または List のいずれかを格納する可能性がありますが、実装については知らないか気にしないので<?>適切です。これと DocumentProcessor の違いは、フォームを拡張しているため、それがモデルをどのように使用しているかを知り、気にかけます。

IColumn

IColumn/PropertyColumn の例では、revisionID フィールドが Long であると仮定して、次のように記述します。

List<PropertyColumn> columns = new ArrayList<PropertyColumn>();
columns.add(new PropertyColumn<Long>(new Model<String>("Number"), "revisionID"));

あなたは見るかもしれません

1.4 移行に関するその他の情報

ボイド型パラメータ

于 2009-12-03T22:39:33.377 に答える
-1

IColumnインターフェイスとPropertyColumnクラスはパラメーター化された型であるため、それらの型パラメーターを定義するだけでよいという警告が表示されます。

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

List<Set> list = new ArrayList<Set>();

ListArrayListはパラメーター化された型であり、それらの型パラメーターが定義されています。ただし、Setもパラメーター化された型ですが、生のバージョンが型パラメーターとして使用されるため、コンパイラーはその場合に警告を生成します。

すべての型引数を明示的に指定することで、例を修正できます。

List<Set<Integer>> list1 = new ArrayList<Set<Integer>>();
List<Set<String>> list1 = new ArrayList<Set<String>>();

ジェネリック クラスとインターフェイスに対しても同じことを行う必要があります。

于 2009-12-01T05:54:46.467 に答える