Java——泛型基本總結(通配符、泛型接口、泛型方法)
目錄
1、泛型的產生背景
2、泛型的通配符?
3、泛型接口(重點)
4、泛型方法
5、總結
JDK1.5后的三大主要特性:泛型、枚舉、Annotation。
1、泛型的產生背景
假如,現在定義一個表示坐標的類,Point,屬性坐標x,y,但是此類設計特殊,現在由于設計特殊,現在實際使用中有可能出現以下三種結構的數據:
整數:x=10、y=10;
小數:x=10.1、y=10.1;
字符串:x=東經10度、y=北緯20度。
可以發現,Point中可以保存三種數據類型,而Point類中只存在xy兩個屬性。現在唯一可以想到的數據類型就是Object類型,因為滿足以下轉換:
保存int:int-》自動裝箱為Integer-》向上轉型為Object;
保存double:double-》自動裝箱為Double-》向上轉型為Object;
保存字符串:String-》向上轉型為Object。
【第一步】:定義Point類
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);
p.setY(10);
int x1 = (Integer)p.getX();
int y1 = (Integer)p.getY();
System.out.println("x="+x1+",y="+y1);
//double數據
p.setX(10.1);
p.setY(10.1);
double x2 = (Double)p.getX();
double y2 = (Double)p.getY();
System.out.println("x="+x2+",y="+y2);
//字符串數據
p.setX("東經10度");
p.setY("北緯20度");
String x3 = (String)p.getX();
Stringy3 = (String)p.getY();
System.out.println("x="+x3+",y="+y3);
以上的操作雖然滿足了要求,但是整個代碼的實現關鍵在于利用了Object類型,利用Object操作的優點是可以接收所有的數據類型,但是Object類要接收數據類型,必須進行強制的向下轉型,存在隱患:
p.setX(100);
p.setY("北緯20度");
String x3 = (String)p.getX();
String y3 = (String)p.getY();
System.out.println("x="+x3+",y="+y3);
以上代碼編譯OK,但是項目運行時會發生錯誤:
以上分析可知,向下轉型這種操作本身存在安全隱患問題,且不能通過編譯檢查出來,用Object類進行這類處理就說有這種問題。那么該問題如何解決呢?唯一的解決方案就是不進行對象的向下轉型。這樣的背景下,就產生了泛型的技術。
泛型的本質:類中的屬性或方法的參數,不設置具體的類型,只使用一個標記表示,而在類使用的時候才對其動態的綁定一種數據類型。
【舉例】:使用泛型
class Point
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;
}
}
此時,Point類中的屬性類型無法確定,必須在類實例化對象的時候動態的綁定。
【舉例】:使用泛型
Point
p.setX("東經10度");
p.setY("北緯20度");
String x = p.getX();
String y = p.getY();
System.out.println("x="+x+",y="+y);
此時我們設置數據時,數據類型不是String,編譯不通過,且取出數據時也不用進行強制向下轉型,消除了安全隱患。
2、泛型的通配符?
現在假設有如下泛型類:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Message
fun(msg);
System.out.println(msg.getInfo());
}
public static void fun(Message
temp.setInfo("HELLO");
}
}
class Message
private T info;
public T getInfo() {
return info;
}
public void setInfo(T info) {
this.info = info;
}
}
泛型類型可以改變,將以上使用的泛型類型由String 變為Integer,此時fun方法不能正常使用,且由于重載是受到參數類型而不是泛型類型的限制,那么無法通過重載來解決此問題。那么該如何解決,需要一種標記滿足以下要求:
可以用于泛型上,這樣可以避免安全警告;
標記使用后,允許接收任何內容,但是不能修改里面的數據;
為此,泛型中提供了一個重要的通配符“?”
【舉例】:使用通配符描述
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Message
msg.setInfo(100);
fun(msg);
}
public static void fun(Message> temp){
System.out.println(temp.getInfo());
}
}
但是,此通配符基礎上又擴展處理兩個子通配符組合:
?extends 類:設置泛型的上限,可以設置在類或方法參數中;
?extends Number:表示可以使用的泛型只能是Number或者Number的子類;
?super 類:設置泛型的下限,可以設置在方法參數中:
?super String:表示只能夠設置String或者其父類。
【舉例】:設置泛型的上限(只能設置數字)
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Message
msg.setInfo(1000);
fun(msg);
}
public static void fun(Message extends Number> temp){
System.out.println(temp.getInfo());
}
}
class Message
private T info;
public T getInfo() {
return info;
}
public void setInfo(T info) {
this.info = info;
}
}
【舉例】:設置泛型 的下限
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Message
msg.setInfo("1111");
fun(msg);
}
public static void fun(Message super String> temp){
System.out.println(temp.getInfo());
}
}
class Message
private T info;
public T getInfo() {
return info;
}
public void setInfo(T info) {
this.info = info;
}
}
后續看開發文檔時,會看見很多這樣的通配符標記,我們要看的懂,我們要掌握?的作用是什么。
3、泛型接口(重點)
在接口上用泛型,就是泛型接口。
interface IMessage
public void print(T t);//方法上使用泛型
}
以上,實現 了泛型接口,但是對于泛型接口的子類,有兩種實現形式:
模式一:子類繼續使用泛型聲明
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MessageImpl
msg.print("hello");
}
interface IMessage
public void print(T t);//方法上使用泛型
}
class MessageImpl
implements IMessage
{
@Override
public void print(P p) {
System.out.println(p);
}
}
}
模式二:子類定義時不使用泛型,直接為父接口設置好泛型類型
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MessageImpl msg = new MessageImpl();
msg.print("hello");
}
interface IMessage
public void print(T t);//方法上使用泛型
}
class MessageImpl implements IMessage
@Override
public void print(String p) {
System.out.println(p);
}
}
}
以上兩種實現模式要掌握,非常重要。
4、泛型方法
若在一個方法使用了泛型,這個方法就稱為泛型方法。
interface IMessage
public void print(T t);//方法上使用泛型
}
泛型方法不一定還要定義在泛型聲明的一個類中,也可能就是一個方法定義為泛型方法。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Integer num[] = fun(1,2,3);
for (Integer n:num){
System.out.println(n);
}
}
public static
return arg;
}
}
現實來講,泛型方法能看懂即可。
5、總結
1)泛型解決的問題就是向下轉型所帶來的安全隱患;
2)泛型的本質:類的屬性或方法的參數可以由用戶在使用時動態設置;
3)通配符?、? extends 類、? super 類。
作于202005112145,已歸檔
———————————————————————————————————
本文為博主原創文章,轉載請注明出處!
若本文對您有幫助,輕抬您發財的小手,關注/評論//,就是對我最大的支持!
祝君升職加薪,鵬程萬里!
Java 數據結構
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。