簡単にオブジェクトを避けることができ、一般的な機能の使用は、潜在的な安全上の問題をキャスト(ClassCastExceptionが異常)
9.4.1一般的な問題のリード
Java言語では、統一受信したパラメータのタイプを容易にするために、すべてのデータ型は、このようなオブジェクトを使用して受信することができる、コアクラスオブジェクトが提供されます。しかし、データが範囲を説明するので大きすぎる、着信データ型エラーが異常原因、実際の使用時に発生し、説明することができるクラスポイントが座標点を考案し、座標点、3種類のデータが格納されていることができ
-
整数データ:X = 10、Y = 20。
-
浮動小数点データ:X = 10.1、Y = 20.9。
-
文字列データ:X = 210度東経、Y = 30度北緯。
あなたは、xとyプロパティの特定のタイプを考慮する必要があり、時間のクラス設計点では、要件のこのタイプは、データの3種類以上のために保存することができ、最も原始的な方法を定義するオブジェクトクラスを使用することであることは明らかです。以下の変換関係。 -
整数データ:基本データ型 - > Integer型クラスオブジェクトのパッケージ - >自動アップキャストオブジェクト。
-
浮動小数点データ:基本データ型 - >クラスのオブジェクトのための二重包装 - >オブジェクトアップキャスト自動。
-
データ文字列:文字列クラスは、オブジェクト- >自動アップキャストオブジェクト。
例:定義Pointクラスの座標点
public 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クラスの属性xとyは、あなたが任意のタイプのデータを受け取ることができるので、この場合は二つの状況が発生する可能性があるように、ストレージObject型として使用されています。
ケース1:ユーザーが統一座標データ型の内容に応じて設けられ、下方に取得された生データの座標変換を使用しています
public class Java214 {
public static void main(String[] args) {
Point ppo=new Point() ;
//第一步,根据需求进行内容的设置,所有数据都通过Object接收
ppo.setX(10); //自动装箱
ppo.setY(20);
//第二步 从里面获取数据由于返回的是Object类型,所以必须进行强制向下转型
int x=(Integer)ppo.getX();
int y=(Integer)ppo.getY();
System.out.println();
}
}
結果
x坐标:10、y坐标:20
ケース2:ユーザーが強制を読み取るデータの間違ったタイプを使用して、コンテンツを座標統一データ型で提供されていません
package com.lxh.ninechapter;
public class java215 {
public static void main(String[] args) {
Point ppo=new Point() ;
//第一步,根据需求进行内容的设置,所有数据都通过Object接收
ppo.setX(10); //自动装箱
ppo.setY("beiwu");//与X数据类型不统一,但是由于符合标准语法,所以编译时无法发现问题
//第二步 从里面获取数据由于返回的是Object类型,所以必须进行强制向下转型
int x=(Integer)ppo.getX();
int y=(Integer)ppo.getY();
System.out.println();
}
}
結果
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at com.lxh.ninechapter.java215.main(java215.java:11)
9.4.2ジェネリックの基本的な定義
。
あなたはClassCastExceptionがプロジェクトが発生する問題を解決したい場合は、下に強制コアプログラム・オブジェクト・キャストを避けるために。したがって、コアの一般的な設計であって、動的マーク、インスタンス化されたオブジェクトのタイプに使用される動的構成データの戻り値のプロパティまたはメソッドパラメータクラスタイプ。
注意:一般的には、参照のみのデータ型を可能にします。
使用時には、髪の起源を定義するためのクラス、特定のデータ型の広い範囲を定義するためのファーストクラスに相当します。
例:クラス定義でジェネリックを使用して
public class Point<T> {//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;
}
}
import java.util.List;
public class Java216 {
public static void main(String[] args) {
//实例化Point对象,设置泛型标记T的目标数据类型,属性、方法参数、返回值类型的动态配置。
Point<Integer> oo=new Point<Integer>();
//第一步,根据需求进行内容的设置,所有数据都通过Object接收
oo.setX(10); //自动装箱
oo.setY(20);
//第二步 从里面获取数据由于返回的是Object类型,所以必须进行强制向下转型
int x=oo.getX(); //避免强制向下转型
int y=oo.getY();//避免强制转型
System.out.println("坐标X:"+x+"、坐标y"+y);
}
}
結果:
座標X:10、Y20座標
ジェネリック型がそのようにxに現在のオブジェクトが、Yは、属性タイプは、対応するパラメーターの整数であることが、整数のために使用された手順と本ポイントクラスオブジェクトに設定されているインスタンス化。戻り値は、これだけはっきりとコンパイル時にエラーのデータタイプを知ることができ、また操作意気消沈オブジェクトを避けるためではなく、整数です。
使用ジェネリッククラスでは、オリジナルのJDKの使用法を開発することができます考慮して、ジェネリック型への開発者がオブジェクトで提供されていない可能ことは、コンパイル時に対応する警告が表示されますので、こと、インスタンス化され、そして順番にエラーが発生しなかったことを確実にし、ジェネリックオブジェクトタイプの設定は、デフォルトのタイプとして使用されます。
例:デフォルトのタイプの観察
public class Java217 {
public static void main(String[] args) {
//实例化Point对象,没有设置泛型类型,编译时出现警告,默认使用Object类型
Point oo=new Point();
//第一步,根据需求进行内容的设置,所有数据都通过Object接收
oo.setX(10); //自动装箱
oo.setY(20);
//第二步 从里面获取数据由于返回的是Object类型,所以必须进行强制向下转型
int x=(Integer)oo.getX(); //避免强制向下转型
int y=(Integer)oo.getY();//避免强制转型
System.out.println("坐标X:"+x+"、坐标y"+y);
}
}
コンパイル時の警告
注:Java217.java使用了未经检查或不安全的操作
注:有关详细信息,请使用-Xlint:unchecked重新编译。
9.4.3一般的なワイルドカード
我々は、異なるジェネリック型のオブジェクト間で互いに参照を渡すことができない
受信した場合に使用することができ、参照オブジェクトのジェネリック型が行われた場合、このオブジェクト・クラスのすべてのインスタンスに適応させることができるように「?」汎用ワイルドカードとして使用、使用?それだけで被験体から得ることができ、そしてデータを変更しないジェネリック型を表しています。
例:使用?データを受信
public class Message<T> { //定义泛型类对象
public T count;
public T getCount() {
return count;
}
public void setCount(T count) {
this.count = count;
}
}
public class Java218 {
public static void main(String[] args) {
Message<String> msg=new Message<String>();
msg.setCount("kkkkkk");
fun(msg);
}
private static void fun(Message<?> temp) { //输出信息,只允取不允许修改存放
//如果现在需要接收则会使用Object作为泛型类型,既String str=(String)temp.getCount()
System.out.println(temp.getCount());
}
}
結果
kkkkkk
このプログラムは楽しい()メソッドのメッセージにパラメータを使用しています。<?>メッセージクラスのオブジェクト参照は、ワイルドカード以来、受け取りましたか?役割は、この方法は、一般的なタイプのいずれかに一致することができますので。
質問:あなたはジェネリック型を設定しないか、ジェネリック型をオブジェクトに設定されている場合は、上記の問題を解決することができます
答え:ジェネリック医薬品は、ユニティの操作の種類を検討する必要があり
、一般的な概念に括弧を異なったタイプの2種類の内、オブジェクトならば、唯一のタイプのオブジェクトを受け入れることができます。
あなたは配送問題の異なるジェネリック型のオブジェクトを解決することができる方法でジェネリック型を設定しませんが、また新たな問題があります場合は、次のデータを自由に変更する許可。
例:観察方法パラメータがジェネリック型を定義する際に設けられていません
public class Java1219 {
public static void main(String[] args) {
Message<String> msg=new Message<String>();
msg.setCount("kkkkkk");
fun(msg);
}
//不设置泛型类型,,表示可以接收任意的泛型类型对象
//默认泛型类型为Object,但是不同于Message<Object>
private static void fun(Message temp) {
//原始类型为String,现在设置Integer
temp.setCount(10);
System.out.println(temp.getCount());
}
}
結果
10
これは、ワイルドカードの使用を変更する制御を行うことはありませんか?のみ取ることが許さジェネリックは、変更することはできません。
一般的な上限と下限
「」一般的なタイプのいずれかと一致するワイルドカード、上限および下限ジェネリッククラス範囲厳しい定義の構成によって実現することができることに加えて:
上部[方法]クラスとジェネリックは(延び?クラス):ジェネリックタイプを設定現在のクラスまたは現在のクラスのサブクラスを使用することしかでき;
「番号を拡張?」:あなたが設定または例えば番号番号サブクラス(CAN:整数、ダブル);
(一般の下限を設定する[方法]?スーパークラス):あなただけの親クラス指定されたクラスを設定したり、指定したクラスをすることができます。
「スーパー文字列を?」:唯一の親クラスオブジェクトの文字列または文字列を設定することができます。
例:一般的な制限を設定します
public class Message<T extends Number> { //定义泛型类对象
public T count;
public T getCount() {
return count;
}
public void setCount(T count) {
this.count = count;
}
}
public class Java219 {
public static void main(String[] args) {
Message<Integer> msg=new Message<Integer>(); //Integer是Number的子类
msg.setCount(10);
fun(msg);
}
private static void fun(Message<? extends Number> t) {
System.out.println(t.getCount());
}
}
結果:10
の目的は、メッセージ番号のみジェネリック型またはサブクラスとして使用インスタンス化することができるように、一般的なセットの上限を用いて
下限汎用の設定:例
public class Message<T> { //定义泛型类对象
public T count;
public T getCount() {
return count;
}
public void setCount(T count) {
this.count = count;
}
}
public class Java220 {
public static void main(String[] args) {
Message<String> msg=new Message<String>();
msg.setCount("520");
fun(msg);
}
private static void fun(Message<? super String> msg) {
System.out.println(msg.getCount());
}
}
結果:520
このプログラムは、一般的な下限、Messageオブジェクトのジェネリック型のみ受信することができ、または親クラスStringを使用しています。
9.4.4一般的なインタフェース
ジェネリッククラスに加えて、上に定義することができ、クラスに定義することができ、このような構成は、汎用インターフェースと呼ばれます。
例:一般的なインタフェースを定義します
public interface IMessage<T> {
public void echo(T msg);
}
サブクラスで一般的な親クラスとサブクラスを提供するジェネリック型宣言を続行:このケースでは、サブクラスの定義時に実装が行われた2つのIMessageが一般的なインターフェースがあります。
例:一般的なインタフェースのサブクラスを定義する、サブクラスでジェネリック型を宣言し続けます
public interface IMessage<T> {
public void echo(T msg);
}
public class MessageImol<S> implements IMessage<S> { //子类继续声明泛型类型
@Override
public void echo(S t) { //方法覆写
System.out.println("ll"+t);
}
}
public class JavaA221 {
public static void main(String[] args) {
IMessage<String> msg=new MessageImol<String>();
msg.echo("520");
}
}
結果
ll520は
本MessageImolサブクラス、およびジェネリック型はMessageImolサブクラスのインスタンス化オブジェクトは、インタフェースIMessafeに伝達され提供された場合、フラグSは、一般的なプログラム定義を宣言し続けます。
例:サブクラスで提供される汎用型へのサブクラスの定義IMessageが
public interface IMessage<T> {
public void echo(T msg);
}
public class MessageImpl implements IMessage<String>{
@Override
public void echo(String msg) { //设置泛型类型,类型为String
System.out.println("lxt"+msg);
}
}
public class JavaB221 {
public static void main(String[] args) {
IMessage<String> msg=new MessageImpl();//实例化子类不设置泛型
msg.echo("520");
}
}
結果
lxt520が
存在する場合、プログラム定義MessageImplジェネリックサブクラスタグを定義していないが、親クラスインターフェースはジェネリック型文字列に設定されているので、上書きエコー()メソッドのパラメータの型が文字列である場合
9.4.5一般的な方法
一般的なため、定義されたクラスの外側に加えて、この方法は、必ずしも一般的なクラスで定義されていない一般的な方法で定義され、この方法で定義することができます。
例:ジェネリックメソッドの定義
public class Java222 {
public static void main(String[] args) {
Integer num[]=fun(1,2,3);//传入了整数,泛型类型就是Integer
for(int a:num) {
System.out.println(a+"、");
}
}
//定义泛型方法,由于类中没有设置泛型类型,所以需要定义一个泛型标记,泛型的类型就是传递的参数类型
public static <T> T[] fun(T...args) { //可变参数
return args;
}
}
結果
1、
2、
3、
このケースではないので楽しい()メソッドがジェネリックタイプによって渡されるパラメータのタイプを決定し、この場合、単一の汎用の宣言タグで定義されなければならないので、一般的なクラス宣言は、一般的な方法で定義されています。