4

一連のありふれたキャストを実行するライブラリが存在するかどうか疑問に思っています(基本的に、ほとんどの場合、実際には問題にならない、潜在的に危険なキャストの束のラッパーです)。たとえば、ライブラリに次のものがあるとします (簡潔にするために本文は省略されています)。

public interface LibraryInterface;

public static void doSomething(Collection<LibraryInterface> collection);

したがって、doSomething()頑固に、可能なものよりも柔軟性の低いものしか取りません(つまりCollection<? extends LibraryInterface>、次のような機能を提供するライブラリはありますか:

public static <T, U extends T> Collection<T> cast(Collection<U> collection);

を実装するクラスがあり、 がある場合LibraryInterface、そのリストをキャストすることでList<MyLibraryInterfaceImpl>引き続き使用できますか? doSomething()( の本体にcast()は、安全でないキャストが含まれていることが暗示されていますが、少なくともユーザーの観点からは、そのキャストは隠されているか、1 か所に集中しています)。

(また、コンパレータのようなものとは逆のことをするものもいいです)

4

3 に答える 3

1

あなたのcast(Collection<U> collection)方法が行うすべてはによって達成することができます<T extends LibraryInterface> doSomething(Collection<T> collection)

ライブラリの余分なポイントは何ですか?

また、APIビルダーが型を不変にすることを決定した場合、それは基本的に、契約を尊重し、提供するLibraryInterfaceか、特定の用途向けに設計されていることを厳密に望んでいることを意味します。また、Javaジェネリックにはtype erasureこれを行うことができます

List<? extends Object> p = new ArrayList<Object>();

しかし今List<? extends Object> p = new ArrayList<? extends Object>(); 、上記は違法です。したがって、最初に型キャストとループなしで、私はそのようなライブラリを実装する他の方法を知りません。

だからあなたがやりたいことのために、ジェネリックは共変でしたか、それは

List<Object> p = new ArrayList<String>();

どんな目的でも、あなたが望むものなら何でも可能だったでしょう。しかし、上記の記述は違法です。したがって、それを単に省略することはできません。

したがって、上記を実行する唯一の方法は、ループしてチェックし、最終的に型キャストすることです。

詳細については、こちらこちらをご覧ください

于 2012-11-21T06:44:14.960 に答える
1

さて、そのような図書館は何をするでしょうか?

void flexibleDoSomething(Collection<? extends LibraryInterface> collection) {
    doSomething((Collection<LibraryInterface>) collection);
}

このメソッドは、ライブラリの価値があるようには見えません。これを行うことで、追加の型安全性を得ることができません。明らかに、最初に他のライブラリを修正する方がはるかに良いでしょう。ただし、いつでもメソッドをインライン化できます。

そのようなライブラリが使用されているのを見た状況がいくつかあります。主に、キャストが頻繁に発生する場合、または一部のキャストが構文的に乱雑である場合に、キャストを単一のクラスに集中させるためです。たとえば、複雑Class<Foo<?>>Class<Foo<Something>>ジェネリックのキャスト。

ジェネリックを使用する場合、コンパイラによって適切にバインドされるように、すべての型を右側に表示する必要があることに注意してください。

public static <T, U extends T> Collection<T> cast(Collection<U> collection);

このメソッドの場合、コンパイラは喜んでそれが であると想定しTますObject

より厳密なジェネリックを取得するには、次のようなものを使用することをお勧めします

public static <T, U extends T> Collection<T> cast(Collection<U> collection, Class<T> clz);

このようにして、実際にT, and を指定することができます (まあ、 ではなくCollection、他の状況の場合)、ユーティリティ メソッドは何らかの型チェックを行うこともできます。

于 2012-11-21T07:16:41.060 に答える