汎用詳細超詳細
8719 ワード
汎用型
JDK 1から5以降、3つの一般的な新しい特性が導入された:汎用、列挙(enum)、注釈(Annotation).ここで、JDK 1.5では汎用は非常に重要な実装技術であり、プログラムのパラメータ変換問題を解決するのに役立つ.
1.問題の引き出し
座標を記述するプログラムクラスPointを定義する必要があるとします.2つの属性x,yを指定する必要があります.この2つのプロパティの内容は、次のように選択できます. x = 10、y = 20 ; x = 10.1、y = 20.1 ; x=東経80度、y=北緯20度 では、まず解決しなければならない問題は、Pointクラスのx、yの属性タイプの問題です.この場合、int、double、Stringが保存される必要があります.javaでは、すべてのタイプを保存できるタイプは1つしかありません.Object型の例:Pointクラスの定義
例:整数座標の設定
例:文字列の設定
以上のコードは問題を解決したように見えますが、問題を解決する鍵はObjectにあり、問題はObjectにも現れます.例:オブザーバの問題
このとき設定側のエラーで座標内容がdoubleとStringに設定されていましたが、受信側がわからず、実行時にClassCastExceptionが発生します.ClassCastExceptionとは、関係のない2つのオブジェクトが強転して現れる異常のことです.このとき文法は何の制限もしませんが、実行中にプログラムエラーが発生したため、下への転換は安全ではない操作であり、危険をもたらすと結論しました.
2.基本使用
汎用とは、クラス定義時にクラス内の属性やメソッド内のパラメータの具体的なタイプを設定するのではなく、クラス使用時に定義することを意味します.このような汎用的な操作を行うには、タイプタグの宣言が必要です.汎用クラスの基本構文:
括弧<>のTはタイプパラメータと呼ばれ、任意のタイプを指す.実際にはこのTは任意に書くことができますが、仕様の目的でJavaはタイプパラメータを表すために単一の大文字を使用することをお勧めします.一般的な例: Tは一般的なクラスを表します. EはElementの意味、またはException異常の意味を表します. KはKeyの意味Vは を表す Valueという意味で、通常Kと併用されています.
クラスが形式的に定義されている場合は、汎用クラスと呼ばれます.注意:汎用型はクラスしか受け入れられません.すべての基本データ型はパッケージクラスを使用する必要があります.ここで、汎用クラスは、以下に示すように、複数のタイプパラメータを受信することができることに注意してください.
例:Pointクラスの定義
開発されたプログラムがダウングレードを避けることができると、セキュリティ上の危険性が解消されることを意味します.汎用的な出現は、下への転換の需要を徹底的に変えた.汎用型を導入した後、タイプが明確に設定されている場合は、設定タイプである.タイプが設定されていない場合、デフォルトはObjectタイプです.
3.汎用方法
汎用型はクラスを定義するだけでなく、メソッドを個別に定義することもできます.例:汎用メソッド定義
汎用メソッドが汎用クラスと少し異なる点は,タイプパラメータ,すなわちカッコの部分が戻り値の前に書かれていることである.のTはタイプパラメータと呼ばれ、メソッドのTはパラメータ化タイプと呼ばれ、実行時の本当のパラメータではありません.もちろん、宣言されたタイプパラメータは、戻り値のタイプとしても使用できます.例:タイプパラメータを使用して値を返す汎用メソッド
汎用メソッドは、次のように汎用クラスと共存できます.
例:汎用メソッドと汎用クラスの共存
上記のコードでは、MyClassは汎用クラスであり、testMethod 1は汎用クラスの一般的な方法であり、testMethod 2は汎用メソッドである.汎用クラスのタイプパラメータは、汎用メソッドのタイプパラメータと対応していません.汎用メソッドは常に自分で定義したタイプパラメータに準拠しています.汎用クラスの実際のタイプパラメータはStringであり,汎用メソッドに伝達されるタイプパラメータはIntegerであり,両者はコヒーレントではない.しかし,混同を避けるために,1つの汎用クラスに汎用メソッドが存在する場合,両者のタイプパラメータは同名でないことが望ましい.例えば、MyClassコードはこのように変更できます.
4.ワイルドカード
プログラムクラスに汎用的な定義を追加すると、ClassCastExceptionの問題は回避されますが、パラメータの統一の問題という新しい状況が発生します.コードを見てください.
以上のプログラムは新しい問題をもたらし、現在汎用的なタイプがStringではなくIntegerに設定されている場合.
必要なソリューション:すべての汎用タイプを受信できますが、ユーザーが勝手に変更することはできません.この場合はワイルドカード「?」を使う必要があります.処理します.例:ワイルドカードの使用
「?」に基づいて、2つのサブワイルドカードが生成されました. ? extendsクラス:汎用上限の設定:たとえば:?extends Numberは、Numberまたはそのサブクラスのみを設定できることを示します.例えば、Integer、Doubleなどです. ? superクラス:汎用下限の設定:たとえば:?super Stringは、Stringとその親オブジェクトのみを設定できることを示します.
注意:上限は宣言に使用でき、変更できません.下限はメソッドパラメータのみで、内容を変更できます!
5.汎用インタフェース
汎用型はクラスに定義できるほか,インタフェースに定義できる場合を汎用インタフェースと呼ぶ.構文:
このインタフェースの実装サブクラスには、サブクラス定義時に汎用を継続する2つの方法の例があります.
例:サブクラスがインタフェースを実装するときに具体的なタイプを明確に示す
6.タイプ消去
汎用はJava 1.5バージョンで導入された概念であり、それ以前は汎用の概念はなかったが、明らかに汎用コードは以前のバージョンのコードとよく互換性がある.これは,汎用情報はコードコンパイル段階にのみ存在し,JVMに入る前に汎用に関する情報は消去され,専門用語はタイプ消去と呼ばれるためである.一般的に言えば、汎用クラスと一般クラスはjava仮想マシン内に特別な場所はありません.
コードを見てみましょう.
印刷結果がtrueになったのは、JVMにおけるMyClassとMyClassの両方がMyClassであるためである.class.
JDK 1から5以降、3つの一般的な新しい特性が導入された:汎用、列挙(enum)、注釈(Annotation).ここで、JDK 1.5では汎用は非常に重要な実装技術であり、プログラムのパラメータ変換問題を解決するのに役立つ.
1.問題の引き出し
座標を記述するプログラムクラスPointを定義する必要があるとします.2つの属性x,yを指定する必要があります.この2つのプロパティの内容は、次のように選択できます.
class Point {
private Object x ;
private Object y ;
public Object getX() {
return x;
}
public void setX(Object x) {
this.x = x;
}
public Object getY() {
return y;
}
public void setY(Object y) {
this.y = y;
}
}
例:整数座標の設定
//
Point p = new Point() ;
p.setX(10); // Object
p.setY(20);
//
int x = (Integer) p.getX() ; // Integer
int y = (Integer) p.getY() ;
System.out.println("x = " +x+",y = "+y);
例:文字列の設定
//
Point p = new Point() ;
p.setX(" 80 ");
p.setY(" 20 ");
//
String x = (String) p.getX() ;
String y = (String) p.getY() ;
System.out.println("x = " +x+",y = "+y);
以上のコードは問題を解決したように見えますが、問題を解決する鍵はObjectにあり、問題はObjectにも現れます.例:オブザーバの問題
//
Point p = new Point() ;
p.setX(10.2);
p.setY(" 20 ");
//
String x = (String) p.getX() ;
String y = (String) p.getY() ;
System.out.println("x = " +x+",y = "+y);
このとき設定側のエラーで座標内容がdoubleとStringに設定されていましたが、受信側がわからず、実行時にClassCastExceptionが発生します.ClassCastExceptionとは、関係のない2つのオブジェクトが強転して現れる異常のことです.このとき文法は何の制限もしませんが、実行中にプログラムエラーが発生したため、下への転換は安全ではない操作であり、危険をもたらすと結論しました.
2.基本使用
汎用とは、クラス定義時にクラス内の属性やメソッド内のパラメータの具体的なタイプを設定するのではなく、クラス使用時に定義することを意味します.このような汎用的な操作を行うには、タイプタグの宣言が必要です.汎用クラスの基本構文:
class MyClass {
T value1;
}
括弧<>のTはタイプパラメータと呼ばれ、任意のタイプを指す.実際にはこのTは任意に書くことができますが、仕様の目的でJavaはタイプパラメータを表すために単一の大文字を使用することをお勧めします.一般的な例:
クラスが形式的に定義されている場合は、汎用クラスと呼ばれます.注意:汎用型はクラスしか受け入れられません.すべての基本データ型はパッケージクラスを使用する必要があります.ここで、汎用クラスは、以下に示すように、複数のタイプパラメータを受信することができることに注意してください.
lass MyClass {
T value1;
E value2;
}
public class Test {
public static void main(String[] args) {
MyClass myClass1 = new MyClass();
}
}
例:Pointクラスの定義
class Point { // T , ;
private T x ;
private T y ;
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public T getY() {
return y;
}
public void setY(T y) {
this.y = y;
}
}
public class Test{
public static void main(String[] args) {
//
Point p = new Point() ; // JDK1.5
p.setX(" 80 ");
p.setY(" 20 ");
//
String x = p.getX() ; //
String y = p.getY() ;
System.out.println("x = " +x+",y = "+y);
}
}
開発されたプログラムがダウングレードを避けることができると、セキュリティ上の危険性が解消されることを意味します.汎用的な出現は、下への転換の需要を徹底的に変えた.汎用型を導入した後、タイプが明確に設定されている場合は、設定タイプである.タイプが設定されていない場合、デフォルトはObjectタイプです.
3.汎用方法
汎用型はクラスを定義するだけでなく、メソッドを個別に定義することもできます.例:汎用メソッド定義
class MyClass{
public void testMethod(T t) {
System.out.println(t);
}
}
汎用メソッドが汎用クラスと少し異なる点は,タイプパラメータ,すなわちカッコの部分が戻り値の前に書かれていることである.のTはタイプパラメータと呼ばれ、メソッドのTはパラメータ化タイプと呼ばれ、実行時の本当のパラメータではありません.もちろん、宣言されたタイプパラメータは、戻り値のタイプとしても使用できます.例:タイプパラメータを使用して値を返す汎用メソッド
class MyClass{
public T testMethod(T t) {
return t;
}
}
汎用メソッドは、次のように汎用クラスと共存できます.
例:汎用メソッドと汎用クラスの共存
class MyClass{
public void testMethod1(T t) {
System.out.println(t);
}
public T testMethod2(T t) {
return t;
}
}
public class Test {
public static void main(String[] args) {
MyClass myClass = new MyClass<>();
myClass.testMethod1("hello ");
Integer i = myClass.testMethod2(100);
System.out.println(i);
}
}
上記のコードでは、MyClassは汎用クラスであり、testMethod 1は汎用クラスの一般的な方法であり、testMethod 2は汎用メソッドである.汎用クラスのタイプパラメータは、汎用メソッドのタイプパラメータと対応していません.汎用メソッドは常に自分で定義したタイプパラメータに準拠しています.汎用クラスの実際のタイプパラメータはStringであり,汎用メソッドに伝達されるタイプパラメータはIntegerであり,両者はコヒーレントではない.しかし,混同を避けるために,1つの汎用クラスに汎用メソッドが存在する場合,両者のタイプパラメータは同名でないことが望ましい.例えば、MyClassコードはこのように変更できます.
class MyClass{
public void testMethod1(T t) {
System.out.println(t);
}
public E testMethod2(E e) {
return e;
}
}
4.ワイルドカード
プログラムクラスに汎用的な定義を追加すると、ClassCastExceptionの問題は回避されますが、パラメータの統一の問題という新しい状況が発生します.コードを見てください.
class Message {
private T message ;
public T getMessage() {
return message;
}
public void setMessage(T message) {
this.message = message;
}
}
public class Test {
public static void main(String[] args) {
Message message = new Message() ;
message.setMessage("Hello World");
fun(message);
}
public static void fun(Message temp){
System.out.println(temp.getMessage());
}
}
以上のプログラムは新しい問題をもたらし、現在汎用的なタイプがStringではなくIntegerに設定されている場合.
public class Test {
public static void main(String[] args) {
Message message = new Message() ;
message.setMessage(99);
fun(message); // , String
}
public static void fun(Message temp){
System.out.println(temp.getMessage());
}
}
必要なソリューション:すべての汎用タイプを受信できますが、ユーザーが勝手に変更することはできません.この場合はワイルドカード「?」を使う必要があります.処理します.例:ワイルドカードの使用
public class Test {
public static void main(String[] args) {
Message message = new Message() ;
message.setMessage(55);
fun(message);
}
// "?" , ,
public static void fun(Message> temp){
//temp.setMessage(100); !
System.out.println(temp.getMessage());
}
}
「?」に基づいて、2つのサブワイルドカードが生成されました.
注意:上限は宣言に使用でき、変更できません.下限はメソッドパラメータのみで、内容を変更できます!
5.汎用インタフェース
汎用型はクラスに定義できるほか,インタフェースに定義できる場合を汎用インタフェースと呼ぶ.構文:
interface IMessage { //
public void print(T t) ;
}
このインタフェースの実装サブクラスには、サブクラス定義時に汎用を継続する2つの方法の例があります.
interface IMessage { //
public void print(T t) ;
}
class MessageImpl implements IMessage {
@Override
public void print(T t) {
System.out.println(t);
}
}
public class Test {
public static void main(String[] args) {
IMessage msg = new MessageImpl() ;
msg.print("Hello World");
}
}
例:サブクラスがインタフェースを実装するときに具体的なタイプを明確に示す
interface IMessage { //
public void print(T t) ;
}
class MessageImpl implements IMessage {
@Override
public void print(String t) {
System.out.println(t);
}
}
public class Test{
public static void main(String[] args) {
IMessage msg = new MessageImpl() ;
msg.print("Hello World");
}
}
6.タイプ消去
汎用はJava 1.5バージョンで導入された概念であり、それ以前は汎用の概念はなかったが、明らかに汎用コードは以前のバージョンのコードとよく互換性がある.これは,汎用情報はコードコンパイル段階にのみ存在し,JVMに入る前に汎用に関する情報は消去され,専門用語はタイプ消去と呼ばれるためである.一般的に言えば、汎用クラスと一般クラスはjava仮想マシン内に特別な場所はありません.
コードを見てみましょう.
class MyClass{
private T message;
public T getMessage() {
return message;
}
public void setMessage(T message) {
this.message = message;
}
public void testMethod1(T t) {
System.out.println(t);
}
}
public class Test {
public static void main(String[] args) {
MyClass myClass1 = new MyClass<>();
MyClass myClass2 = new MyClass<>();
System.out.println(myClass1.getClass() == myClass2.getClass());
}
}
印刷結果がtrueになったのは、JVMにおけるMyClassとMyClassの両方がMyClassであるためである.class.