JDK1.5--)很重要的特性——泛型
阿新 • • 發佈:2019-01-01
JDK1.5–)很重要的特性——泛型
首先我們要了解:什麼是向下轉型和向上轉型。
- 面向物件的轉型只會發生在具有繼承關係的父子類中(介面也是繼承的一種)
- 向上轉型:其核心目的在於引數的統一上,根本不需要強制型別轉換。
- 向下轉型:是為了操作子類定義的特殊功能,需要強制型別轉換,可是現在存在的問題是:向下轉型其實是一種非常不安全的操作,以為編譯的時候,程式不會報錯,而在執行的時候會報錯,這就是傳說中的—迷之報錯。
- 不過呢,在JDK1.5之後,新增加了泛型的技術,這就將上述向下轉型的問題消滅在了萌芽之中。
- 泛型的核心意義在於:類在進行定義的時候可以使用一個標記,此標記就表示類中屬性或者方法以及引數的型別,標記在使用的時候,才會去動態的設定型別。
- 原始碼如下:
首先來看看:座標程式碼滿足整型:
package cn.dujiang.demo;
class Point { //定義地置
private Object x ;
private Object y ;
public void setX(Object x) {
this.x = x;
}
public void setY(Object y) {
this.y = y;
}
public Object getX() {
return x;
}
public Object getY() {
return y;
}
}
public class TestDemo {
public static void main(String[] args) {
//1.設定資料
Point p = new Point() ;
p.setX(10);
p.setY(20);
//2.取出資料
int x = (Integer) p.getX();
int y = (Integer) p.getY();
System.out .println("x地置"+ x +",y地置"+ y);
}
}
座標程式碼滿足字串的:
package cn.dujiang.demo;
class Point { //定義座標
private Object x ;
private Object y ;
public void setX(Object x) {
this.x = x;
}
public void setY(Object y) {
this.y = y;
}
public Object getX() {
return x;
}
public Object getY() {
return y;
}
}
public class TestDemo {
public static void main(String[] args) {
//1.設定資料
Point p = new Point() ;
p.setX("東經:100°");
p.setY("北緯:20°");
//2.取出資料
String x = (String) p.getX();
String y = (String) p.getY();
System.out.println("x地置"+ x +",y地置"+ y);
}
}
再來看看:泛型的基本表現形式:
package cn.dujiang.demo;
//此時設定的T在Point類定義上,只表示一個標記,在使用的時候需要為其設定具體的型別
class Point<T> { //定義座標,這個"<>"裡面的東西隨意,Type = T,是表示一種型別
private T x ; //此屬性的型別不確定,由Point類使用時動態決定
private T y ; //此屬性的型別不確定,由Point類使用時動態決定
public void setX(T x) {
this.x = x;
}
public void setY(T y) {
this.y = y;
}
public T getX() {
return x;
}
public T getY() {
return y;
}
}
//在使用Point類的時候才設定標記的內容,也就是設定了類中的屬性的型別。
//下面用String試試:
public class TestDemo {
public static void main(String[] args) {
//1.設定資料
Point<String> p = new Point<>() ; //JDK1.7之後例項化的泛型可以省略。
//加入設定的資料型別是錯誤的,那麼在編譯的時候就會自動的排查了
p.setX("東經:10°");
p.setY("北緯:20°");
//2.取出資料,由於我們接收的型別就是String,所以不需要向下強制轉換
String x = p.getX();
String y = p.getY();
System.out.println("x地置"+ x +",y地置"+ y);
}
}
//輸出之後發現,所有類中屬性的型別,都是動態設定的,而所有使用泛型標記的方法引數型別也都發生改變,這樣
//就相當於避免了向下轉型的問題,從而解決了轉換的安全問題
泛型的萬用字元:
package cn.dujiang.demo;
class Message<T> {
private T msg ;
public void setMsg(T msg) {
this.msg = msg;
}
public T getMsg() {
return msg;
}
}
public class TestDemo {
public static void main(String[] args) {
Message<Integer> m1 = new Message<Integer>();
Message<String> m2 = new Message<String>();
m1.setMsg(10);
m2.setMsg("Hello World");
fun(m1) ;//引用傳遞
fun(m2) ;
}
public static void fun(Message temp){
System.out.println(temp.getMsg());
}
}
/*以上程式碼為Message類設定的是一個String型的泛型型別,但是如果說
現在設定的型別變了,那麼fun()方法裡面接收的"Message<String>"那麼就不能夠使用了,並且
fun()方法不能夠針對不同的泛型進行過載,因為方法的過載認的只是引數的型別,與泛型無關
解決方法1.不設定泛型引數的泛型
*/
在介面上必須定義其相應的子類,如果要定義子類有以下兩種方式:
- 在子類上不設定泛型,但是在父類介面上要明確定義一個泛型。程式碼如下:
package cn.dujiang.demo;
interface IMessage<T>{//設定泛型介面
public void print(T t) ;
}
//子類也繼續使用泛型,並且父介面使用和子類同樣的泛型標記
class MessageImpl implements IMessage<String> {
@Override
public void print(String t) {
// TODO Auto-generated method stub
System.out.println(t);
}
}
public class TestDemo {
public static void main(String[] args) {
IMessage<String> msg = new MessageImpl();
msg.print("Hello World!") ;
}
}
- 在子類上繼承例項化泛型
package cn.dujiang.demo;
interface IMessage<T>{//設定泛型介面
public void print(T t) ;
}
//子類也繼續使用泛型,並且父介面使用和子類同樣的泛型標記
class MessageImpl<T> implements IMessage<T> {
public void print(T t){
System.out.println(t);
}
}
public class TestDemo {
public static void main(String[] args) {
IMessage<String> msg = new MessageImpl<String>();
msg.print("Hello World!") ;
}
}
總結:泛型主要針對向下轉型時所帶來的安全隱患,其核心組成是在宣告類或介面時,不設定引數或屬性的型別。