JAVASE之JAVA泛型篇

markriver發表於2021-09-09

一 概述

        泛型,JDK1.5新加入的,解決資料型別的安全性問題,其主要原理是在類宣告時透過一個標識表示類中某個屬性的型別或者是某個方法的返回值及引數型別。這樣在類宣告或例項化時只要指定好需要的具體的型別即可。 Java泛型可以保證如果程式在編譯時沒有發出警告,執行時就不會產生ClassCastException異常。同時,程式碼更加簡潔、健壯。如下圖描述:

圖片描述

二 使用泛型

1.宣告

       interface List 和 class TestGen ,其中,T,K,V不代表值,而是表示型別。這裡使用任意字母都可以。常用T表示,是Type的縮寫。

2.泛型的例項化

一定要在類名後面指定型別引數的值(型別)。如:

        ListstrList = new ArrayList();

       Iterator iterator = customers.iterator();

T只能是類,不能用基本資料型別填充。

注:

1.物件例項化時不指定泛型,預設為:Object

2.泛型不同的引用不能相互賦值。

3.加入集合中的物件型別必須與指定的泛型型別一致。

圖片描述

三 自定義泛型

下面舉一個例子:

Dao.java

package com.lxj.generics;

//父介面
public interface Dao {
	
	//泛型方法
	public  T getT(T t);
	
}

JdbcDaoImpl.java

package com.lxj.generics;

public class JdbcDaoImpl implements Dao{

	@Override
	public  T getT(T t) {
		return t;
	}

}

CustomerDao.java

package com.lxj.generics;

public class CustomerDao extends JdbcDaoImpl{
   
}

PersonDao.java

package com.lxj.generics;

public class PersonDao extends JdbcDaoImpl{

}

Customer.java

package com.lxj.generics;

public class Customer {

	private int id;
	private String name;
	private Integer age;

	public Customer() {
		
	}
	
	public Customer(int id,String name,Integer age) {
		 this.id = id;
		 this.name = name;
		 this.age = age;
	}
	
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	@Override
	public String toString() {
		return "Customer [id=" + id + ", name=" + name + ", age=" + age + "]";
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

}

Person.java

package com.lxj.generics;

public class Person {

	private int id;
	private String name;
	private Integer age;

	public Person() {
		
	}
	
	public Person(int id,String name,Integer age) {
		 this.id = id;
		 this.name = name;
		 this.age = age;
	}
	
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}


	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

}

TestGenerics.java

package com.lxj.generics;

public class TestGenerics {
	public static void main(String[] args) {
		CustomerDao customerDao = new CustomerDao();
		Customer customer = customerDao.getT(new Customer(1,"zhangsnag",4));
		System.out.println(customer);
		
		PersonDao personDao = new PersonDao();
		Person person = personDao.getT(new Person(1,"zhangsnag",4));
		System.out.println(person);
	}
}

執行結果:

Customer [id=1, name=zhangsnag, age=4]
Person [id=1, name=zhangsnag, age=4]

從這個例子我們會發現JdbcDaoImpl具有通用性,假如是CustomerDao,直接繼承JdbcDaoImpl就行了,如果想擴充套件,加一個PersonDao,直接繼承JdbcDaoImpl就可以,寫明泛型型別就好了,透過泛型型別,JVM能夠識別不同的型別。


四 萬用字元

1.使用型別萬用字元:?

比如:List>   ,Map,?>

List>是List、List等各種泛型List的父類。

2.List>的物件list中的元素時,永遠是安全的,因為不管list的真實型別是什麼,它包含的都是Object。

3.寫入list中的元素時,不行。因為我們不知道c的元素型別,我們不能向其中新增物件。

Ø唯一的例外是null,它是所有型別的成員。

將任意元素加入到其中不是型別安全的

Collection> c = new ArrayList();

c.add(new Object()); // 編譯時錯誤

因為我們不知道c的元素型別,我們不能向其中新增物件。

        add方法有型別引數E作為集合的元素型別。我們傳給add的任何引數都必須是一個未知型別的子類。因為我們不知道那是什麼型別,所以我們無法傳任何東西進去。

唯一例外null,它是所有型別的成員另一方面,我們可以呼叫get()方法並使用其返回值。返回值是一個未知的型別,但是我們知道,它總是一個Object。

>   允許所有泛型的引用呼叫

extends Number>     (無窮小 , Number]

只允許泛型為Number及Number子類的引用呼叫

super Number>      [Number , 無窮大)

只允許泛型為Number及Number父類的引用呼叫

extends Comparable>

只允許泛型為實現Comparable介面的實現類的引用呼叫

同樣是之前的例子:

新增加一個 Animal.java 類

package com.lxj.generics;

public class Animal {

}

Customer 類 Person類都繼承Animal 類,JdbcDaoImpl 類的泛型如下:

package com.lxj.generics;

public class JdbcDaoImpl implements Dao{

	@Override
	public  T getT(T t) {
		return t;
	}

}













來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/818/viewspace-2811179/,如需轉載,請註明出處,否則將追究法律責任。

相關文章