2017-02-05 6 views
3

下位ワイルドカードが存在する理由の1つは、新しい要素を追加するときにコレクションが不変ではないということです。下界ワイルドカードJava - メソッドへのアクセス

など。

私は数値の長い値を取得しようとしたため、以下はコンパイルされません。

1:どのような方法を使用できますか? は、私は現在のストリームについて学んでいますし、書籍には、次のストリーム方法を指定:

Optional<T> min(Comparator<? super T> comparator) 

そして道具を唯一の方法?:

public void testLowerBounds(List<? super Number> numbers){ 
     if (!numbers.isEmpty()){ 
      System.out.println(numbers.get(0).longValue());//Does not compile 
     }  

}

私の質問は、約来てどのようにオブジェクトそれは次の通りです:

Stream<String> s = Stream.of("monkey", "ape", "bonobo");  
Optional<String> min = s.min((s1, s2) -> s1.length()—s2.length()); 

Q2:コンパレータは、文字列メソッドの使用時にどのように文字列メソッドを使用できますか?

私はQ2に答えなければならなかった:オプションは "あなたにジェネリックタイプ" String "を持つComparatorの実装を渡すか、" String "を実装するものを指定しなければならないと言います。この?

はあなたの応答を楽しみにしています。すべての

+0

これらは2つの異なる質問であるようです。最初の前提として、コンパイラがリストに追加することを妨げると、リストが不変であるという意味ではありません。コンパイラは、単に言語の静的型チェックの規則に従っています。 – manouti

+0

また、 'List'には' longValue() 'メソッドがありません。 – manouti

+0

こんにちはAR.3フィードバックに感謝します。私はあなたが正しいように質問を変更した、私は内容の代わりにリストメソッドをチェックしていた。彼らは確かに2つの異なる質問です、私はちょうど質問の起源を説明したかった。私は、不変についてあなたが言っていることを得るが、コンパイラはあなたがリストに追加させないので、今は論理的に不変である。どちらの質問にも答えがありますか? –

答えて

1

まず、あなたは可変性とワイルドカードの型パラメータを混同してはならない。Listの要素型でワイルドカードを持つことを修正、それだけ課しを防ぐことはできません。いくつか実用的なあなたがlisでできることに制限t。 のように宣言されたリストを有することは、参照されるリストがNumberの実際の要素タイプまたはNumberのサブクラスを有することを意味する。 List<Integer>またはList<Double>となります。したがって、任意のNumberインスタンスを追加することはできません。実際の要素タイプと互換性があるかどうかはわかりません。

nullの参照はすべての参照型と互換性があることが知られているので、nullを追加することはできます。さらに、リストから要素を削除することもできます(例: removeまたはclearを問題なく使用してください。また、Collections.swap(list, index1, index2)のようなメソッドを呼び出すこともできます。これは、ワイルドカード型に関する正式な規則のためにlist.set(index1, list.get(index2))を呼び出すのは正当ではないので興味深いですが、リストを渡すことはできません。タイプの作品です。それは互換性がなければならない同じリストに由来する要素を設定するだけなので、明らかに正しいです。

同様に、Comparator<Number>がある場合、Collections.sort(list, comparator)を呼び出すことができます。任意の数値を処理できるコンパレータとして、リストに実際に格納されている数値を処理できます。

集計すると、コレクションの要素タイプに? extendsがあると、でなく、の変更を防ぐことができます。


としては、あなたが実際の要素タイプList<? extends Number>持つようにバインドされた未知のサブクラスで、あるかもしれないリストに任意の新しい要素を挿入することはできません、と述べました。しかし、サブタイプのすべてのインスタンスNumberもまたNumberのインスタンスであるため、要素を取得するときにはNumberインスタンスを取得することが保証されます。 を宣言すると、その実際の要素タイプはNumberまたはNumberのスーパータイプです。 ObjectまたはSerializable。任意のNumberインスタンスを挿入することができます。これは、スーパータイプの番号であるため、実際の要素タイプと互換性があることがわかっています。インスタンスを取得するときは、すべてのインスタンスのスーパータイプであるため、インスタンスがObjectであることだけがわかります。 ? extendsの場合と比較すると、? superの宣言を行っても読み取りが妨げられることはありませんが、実際的な制限があります。同様に、実際のタイプについてわかっていないにもかかわらず、同じリストから検索したものを挿入すると、機能するため、まだCollections.swapに渡すことができます。

2番目の質問では、両側を混乱させています。現在、minの実装は見ていませんが、の呼び出し元にあります。 min(Comparator<? super T> c)の宣言により、呼び出し元は、TまたはTのスーパータイプでパラメータ化されているコンパレータを渡すことができます。だから、Stream<String>を持っている場合、Comparator<String>minメソッドに渡すことが有効です。これはちょうど(s1, s2) -> s1.length()—s2.length()ラムダ式を使って実装しているものです(しかし、私はComparator.comparingInt(String::length)を好むでしょう)。

minの実装では、TまたはComparatorの実際の型引数のどちらが、実際には何も知られていません。しかし、タイプTのストリーム要素は、比較器のcompareメソッドに渡すことができます。これは、TまたはスーパータイプTが必要な場合があります。

+0

ありがとう@Holger。あなたは素敵な説明がありました。私は特に私の2番目の質問への答えが好きです(途中でニースラムダ、メソッド参照を使用)。私は変更についてあなたのポイントを得る。私の最初の質問に対する答えで、私はあなたがその時点で利用可能な情報であるように参照型がオブジェクトになる可能性があるため、私が期待したものであるObjectメソッドのみにアクセスできると言っています。 –

関連する問題