Java汎用型パラメータの限界
12343 ワード
さぎょう
1.制限タイプパラメータのタイプ
要素タイプがIntegerの対偶にアクセスするクラスIntegerPairを定義するには、次のように書くことができます.
タイプパラメータ後のextendsキーワードはTの上界がIntegerタイプであることを示し、コンパイラはタイプ消去段階でTをIntegerに置き換え、生成したバイトコードは以下のようになる.
IntegerPairのサポートタイプはIntegerとそのサブタイプの要素であるため、BoundTestはコンパイルされません.
IntegerParのタイプパラメータTの限界はInteger、IntegerPair setFirstの署名は(Ljava/lang/Integer;)Vであるため、BoundTestをコンパイルする際にエラーが発生します.integerPar setFisrtがStringタイプであるためです.
2.汎用アルゴリズムの実現
NaturalNumberに示すように、タイプパラメータによって境界を呼び出す方法があります.
タイプパラメータTの限界はIntegerであるため、initValue.のようにT上でIntegerを呼び出すことができる方法が汎用アルゴリズムを実現する鍵である.リスト内の要素より大きいものを求めるアルゴリズムを検討します.
演算子>はshort,int,long,double,float,byte,charなどの基礎データ型でのみ操作でき、Objectに対して>操作できないため、コンパイラはエラーを報告します.
この問題はcountGreaterThanメソッドが通用しないことを招く.タイプパラメータに限界を付けると、この問題をうまく解決できます.
新しい汎用アルゴリズムは次のとおりです.
マルチリミット
1つのタイプのパラメータには複数の境界があり、次のように表現できます.
タイプ変数Tのタイプは、境界リストのいずれかのタイプのサブクラス.zhu'ru注意:タイプパラメータの境界がクラスである場合、MultiBounds.javaに示すように、境界リストの最初の位置に置く必要があります.
Dのタイプパラメータの境界クラステーブル音が次のように明示されている場合、Bはインタフェースであり、クラスAは境界リストの2番目の位置に置かれているため、コンパイラはエラーを報告する.
小結
タイプパラメータの限界はタイプ変数のタイプを制限するために使用することができ、汎用アルゴリズムを実現する鍵である.タイプ変数には複数の境界があります.
1.制限タイプパラメータのタイプ
要素タイプがIntegerの対偶にアクセスするクラスIntegerPairを定義するには、次のように書くことができます.
public class IntegerPair<T extends Integer>
{
public IntegerPair() { first = null; second = null; }
public IntegerPair(T first, T second) { this.first = first; this.second = second; }
public T getFirst() { return first; }
public T getSecond() { return second; }
public void setFirst(T newValue) { first = newValue; }
public void setSecond(T newValue) { second = newValue; }
private T first;
private T second;
}
タイプパラメータ後のextendsキーワードはTの上界がIntegerタイプであることを示し、コンパイラはタイプ消去段階でTをIntegerに置き換え、生成したバイトコードは以下のようになる.
Compiled from "IntegerPair.java"
public class generic.bound.IntegerPair {
public generic.bound.IntegerPair();
descriptor: ()V
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: aload_0
5: aconst_null
6: putfield #2 // Field first:Ljava/lang/Integer;
9: aload_0
10: aconst_null
11: putfield #3 // Field second:Ljava/lang/Integer;
14: return
public generic.bound.IntegerPair(T, T);
descriptor: (Ljava/lang/Integer;Ljava/lang/Integer;)V
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: aload_0
5: aload_1
6: putfield #2 // Field first:Ljava/lang/Integer;
9: aload_0
10: aload_2
11: putfield #3 // Field second:Ljava/lang/Integer;
14: return
public T getFirst();
descriptor: ()Ljava/lang/Integer;
Code:
0: aload_0
1: getfield #2 // Field first:Ljava/lang/Integer;
4: areturn
public T getSecond();
descriptor: ()Ljava/lang/Integer;
Code:
0: aload_0
1: getfield #3 // Field second:Ljava/lang/Integer;
4: areturn
public void setFirst(T);
descriptor: (Ljava/lang/Integer;)V
Code:
0: aload_0
1: aload_1
2: putfield #2 // Field first:Ljava/lang/Integer;
5: return
public void setSecond(T);
descriptor: (Ljava/lang/Integer;)V
Code:
0: aload_0
1: aload_1
2: putfield #3 // Field second:Ljava/lang/Integer;
5: return
}
IntegerPairのサポートタイプはIntegerとそのサブタイプの要素であるため、BoundTestはコンパイルされません.
public class BoundTest {
public static void main(String[] args) {
IntegerPair integerPair = new IntegerPair();
integerPair.setFirst("text");
}
}
IntegerParのタイプパラメータTの限界はInteger、IntegerPair setFirstの署名は(Ljava/lang/Integer;)Vであるため、BoundTestをコンパイルする際にエラーが発生します.integerPar setFisrtがStringタイプであるためです.
BoundTest.java:12: error: incompatible types: String cannot be converted to Integer
integerPair.setFirst("text");
^
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error
2.汎用アルゴリズムの実現
NaturalNumberに示すように、タイプパラメータによって境界を呼び出す方法があります.
public class NaturalNumber<T extends Integer> {
private T n;
public NaturalNumber(T n) { this.n = n; }
public boolean isEven() {
return n.intValue() % 2 == 0;
}
// ...
}
タイプパラメータTの限界はIntegerであるため、initValue.のようにT上でIntegerを呼び出すことができる方法が汎用アルゴリズムを実現する鍵である.リスト内の要素より大きいものを求めるアルゴリズムを検討します.
public static int countGreaterThan(T[] anArray, T elem) {
int count = 0;
for (T e : anArray)
if (e > elem) // compiler error
++count;
return count;
}
演算子>はshort,int,long,double,float,byte,charなどの基礎データ型でのみ操作でき、Objectに対して>操作できないため、コンパイラはエラーを報告します.
GenericAlgorithm.java:19: error: bad operand types for binary operator '>'
if (e > elem) // compiler error
^
first type: T
second type: T
where T is a type-variable:
T extends Object declared in method <T>countGreaterThan(T[],T)
1 error
この問題はcountGreaterThanメソッドが通用しないことを招く.タイプパラメータに限界を付けると、この問題をうまく解決できます.
public interface Comparable<T> {
public int compareTo(T o);
}
新しい汎用アルゴリズムは次のとおりです.
public static > int countGreaterThan(T[] anArray, T elem) {
int count = 0;
for (T e : anArray)
if (e.compareTo(elem) > 0)
++count;
return count;
}
マルチリミット
1つのタイプのパラメータには複数の境界があり、次のように表現できます.
タイプ変数Tのタイプは、境界リストのいずれかのタイプのサブクラス.zhu'ru注意:タイプパラメータの境界がクラスである場合、MultiBounds.javaに示すように、境界リストの最初の位置に置く必要があります.
public class MultiBounds {
static class A {
public void a() {
}
}
interface B {
void b();
}
interface C {
void c();
}
static class D {
public void d(T t) {
t.a();
t.b();
t.c();
}
}
public static void main(String[] args) {
D d = new D();
d.d(new A());
}
}
Dのタイプパラメータの境界クラステーブル音が次のように明示されている場合、Bはインタフェースであり、クラスAは境界リストの2番目の位置に置かれているため、コンパイラはエラーを報告する.
D
小結
タイプパラメータの限界はタイプ変数のタイプを制限するために使用することができ、汎用アルゴリズムを実現する鍵である.タイプ変数には複数の境界があります.