Java中泛型的基礎到提高《精簡》
<span style="font-family: SimHei; background-color: rgb(255, 255, 255);"> </span><span style="font-family: SimHei; background-color: rgb(255, 255, 255);"> </span><span style="font-family:SimHei;font-size:24px;color:#ff0000;">泛型初級</span>
<span style="font-family: SimHei; background-color: rgb(255, 255, 255); font-size: 18px;"><span style="white-space:pre"> </span>泛型的由來:</span>
集合中可以儲存任意型別物件,但是在取出時,如果要使用具體物件的特有方法時,
需要進行向下轉型,如果儲存的物件型別不一致,在轉型過程中就會出現ClassCastException異常。
這樣就給程式帶來了不安全性。
在jdk1.5以後就有了解決方案——泛型技術:在儲存元素時,就不允許儲存不同型別的元素。
儲存了就編譯失敗。 所以就需要在儲存元素時,在容器上明確具體的元素型別,這其實和陣列定義很像。
泛型的好處:
1)將執行時期的ClassCastException異常轉移到了編譯時期,進行檢查,並以編譯失敗來體現。 這樣有利於程式設計師儘早解決問題。(不會再執行中出現異常,在編譯時候就能夠發現錯誤)(泛型規定不能只能是自己的型別或者是子類)
2)避免了向下轉型(強轉)的麻煩。
程式碼說明一切:
package cn.hncu.generic;
//泛型能夠限制型別。
public class genericdemo1 {
public static void main(String[] args) {
Mygeneric<Worker> generic =new Mygeneric<Worker>();
generic.add(new Worker());
//generic.add(00); 自己定義了泛型,只能是Worker型別的
// generic.add(new Student());//同樣的報錯,只能新增相同型別的資料
System.out.println(generic);
Mygeneric<Student> s=new Mygeneric<Student>();
s.add(new Student());
// s.add(new Worker());//編譯通不過,出錯,只能新增泛型定義的資料
}
}
class Mygeneric <QQ>{//自己定義泛型,隨便寫寫,最重要的是<>裡面的內容必須與下面的一致,內容隨便寫都可以
QQ obj;
public void add(QQ obj){//由於前面限制,所以只能新增QQ型別的資料
System.out.println("add:"+obj);
}
public QQ out(){
return obj;
}
@Override
public String toString() {
return "Mygeneric [obj=" + obj + "]";
}
}
class Worker{
}
class Student{
}
使用泛型的動機舉例(以集合為例):
對集合中存放元素的型別進行限定,防止後期出錯。如果限定某個集合只能存放Person類物件(因為後期會把元素取出來當作Person物件來處理),這樣放其它型別的物件在編譯時就會報錯。相當於把一個類泛化成很多個不同型別(具體化,限定化)的類。泛型使用的程式碼如:
List<Person> persons = new ArrayList<Person>;
Map<String,String> m = new HashMap<String,String>;
注意:當一個變數被宣告為泛型時,只能被例項變數和方法呼叫,而不能被靜態變數和方法呼叫。原因很簡單,引數化的泛型是一些例項。靜態成員是被類的例項和引數化的類所共享的,所以靜態成員不應該有型別引數和他們關聯。 當一個類要操作的引用資料型別不確定的時候,可以將該型別定義一個形參。用到的這類時,由使用者來通過傳遞型別引數的形式,來確定要操作的具體的物件型別。 什麼時候使用泛型類呢?只要類中操作的引用資料型別不確定的時候,就可以定義泛型類。 有了泛型類,省去了曾經的強轉和型別轉換異常的麻煩。
部分程式碼:
class Mygen<E>{
public void add(E e){
System.out.println(e.toString());
}
public Object out(Object obj){//方法不帶泛型,當返回時候需要強轉,不是很安全
return obj;
}
public <A> A myout(A a){//方法帶泛型,但要求和類的泛型相互獨立。可以限定返回型別和方法的實參相同,更安全,而且不用強轉。
System.out.println("myout:" +a);
return a;
}
// //靜態方法帶泛型,泛型一定要獨立於類,因為它沒有物件。
public static <E> E myout1(E a){
System.out.println("myout:" +a);
return a;
}
完整簡單程式碼演示《細節都在程式碼解釋中》:
package cn.hncu.generic;
public class genericdemo2 {
public static void main(String[] args) {
Mygen<String > my =new Mygen<String>();
my.add("abc");
//my.add(21);//編譯錯誤,泛型規定只能使用String型別的
String s=(String) my.out("asd");//方法不帶泛型,返回值需要強轉,不是很安全
//返回值也必須是泛型型別; 泛型很安全
//方法帶泛型,但要求和類的泛型相互獨立。可以限定返回型別和方法的實參相同,更安全,而且不用強轉。
int m=my.myout(11);//myout:11;返回值和傳進去的引數型別必須一致;
char c=my.myout1('a');
}
}
class Mygen<E>{
public void add(E e){
System.out.println(e.toString());
}
public Object out(Object obj){//方法不帶泛型,當返回時候需要強轉,不是很安全
return obj;
}
public <A> A myout(A a){//方法帶泛型,但要求和類的泛型相互獨立。可以限定返回型別和方法的實參相同,更安全,而且不用強轉。
System.out.println("myout:" +a);
return a;
}
// //靜態方法帶泛型,泛型一定要獨立於類,因為它沒有物件。
public static <E> E myout1(E a){
System.out.println("myout:" +a);
return a;
}
}
當某些類用的介面泛型時候,我們也能解決,要求返回和類一樣和不一樣的型別的泛型都能解決,詳見線面程式碼:package cn.hncu.generic;
public class genericdemo2 {
public static void main(String[] args) {
Mygen<String > my =new Mygen<String>();
my.add("abc");
//my.add(21);//編譯錯誤,泛型規定只能使用String型別的
String s=(String) my.out("asd");//方法不帶泛型,返回值需要強轉,不是很安全
//返回值也必須是泛型型別; 泛型很安全
//方法帶泛型,但要求和類的泛型相互獨立。可以限定返回型別和方法的實參相同,更安全,而且不用強轉。
int m=my.myout(11);//myout:11;返回值和傳進去的引數型別必須一致;
char c=my.myout1('a');
}
}
class Mygen<E>{
public void add(E e){
System.out.println(e.toString());
}
public Object out(Object obj){//方法不帶泛型,當返回時候需要強轉,不是很安全
return obj;
}
public <A> A myout(A a){//方法帶泛型,但要求和類的泛型相互獨立。可以限定返回型別和方法的實參相同,更安全,而且不用強轉。
System.out.println("myout:" +a);
return a;
}
// //靜態方法帶泛型,泛型一定要獨立於類,因為它沒有物件。
public static <E> E myout1(E a){
System.out.println("myout:" +a);
return a;
}
}
泛型高階:
泛型的萬用字元:?
當操作的不同容器中的型別都不確定的時候,而且使用的都是元素從Object類中繼承的方法,
這時泛型就用萬用字元?來表示即可。(助理解的比方: 泛型中的多型應用)。
當我們的集合中輸出的兩個集合是父子關係,就可以採用萬用字元輸出(最簡單的比喻):程式碼如下
package cn.hncu.generic;
import java.util.ArrayList;
import java.util.Iterator;
public class genericPrint {
public static void main(String[] args) {
ArrayList<String> list=new ArrayList<String>();
list.add("qwe");
list.add("qw1e");
list.add("qw2e");
list.add("qw3e");
ArrayList<Integer> list1=new ArrayList<Integer>();
list1.add(1);
list1.add(2);
list1.add(3);
list1.add(4);
list1.add(5);
print(list);
print(list1);
}
private static void print(ArrayList<?> list) {//
Iterator<?> it =list.iterator();
while(it.hasNext())
{
Object obj =it.next();
System.out.println(obj);
}
}
//因為這是執行期的多型,而我們的泛型在編譯期
// private static void print(ArrayList<Object> list) {
// Iterator<Object> it=list.iterator();
// while(it.hasNext()){
// Object obj =it.next();編譯通不過;
// System.out.println(obj);
// }
//
// }
}
還有就是用到上限與下限
演示上限或者下限的應用體現(以TreeSet容器為例):
TreeSet的構造方法:
TreeSet(Collection<? extends E> c)
TreeSet(Comparator<? super E> comparator)
一般情況下:
只要是往容器中新增元素時,使用上限。 ? extends E
只要是從容器中取出元素時,是用下限。 ? super E
如在如下程式碼中,person為父類,Studentdemo為子類,當要求兩個一起輸出時候,可以採用上限,當要求比較大小採用通用的比較器的進行比較就可以用到下限,因為所有的子類都可以採用服類物件進行比較,具體程式碼如下:
package cn.hncu.generic;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
public class genericTopanddown {
public static void main(String[] args) {
// extendsdemo();//上限演示
superdemo();
}
private static void extendsdemo() {
ArrayList<Person> col=new ArrayList<Person>();
col.add(new Person("aa", 12));
col.add(new Person("bb", 19));
col.add(new Person("cc", 14));
/*
* boolean addAll(int index, Collection<? extends E> c)
將指定 collection 中的所有元素都插入到列表中的指定位置(可選操作)。
*/
//能夠實現一次性輸出具有繼承關係的物件
ArrayList<Studentdemo> cols=new ArrayList<Studentdemo>();//泛型的上限,<? extends E>
cols.add(new Studentdemo("ee", 15));
cols.add(new Studentdemo("ff", 16));
cols.add(new Studentdemo("gg", 17));
// col.addAll(cols);//這樣寫不安全,我們是已知二者存在的關係下,嚴謹必須在使用一個集合放相同的型別
//外加排序 用TreeSet
TreeSet<Person> set=new TreeSet<Person>();//必須實現compare介面
set.addAll(col);
set.addAll(cols);
Iterator<Person> it=set.iterator();//迭代器遍歷
while(it.hasNext()){
Person p=it.next();
System.out.println(p);
}
}
//下限演示
private static void superdemo() {
TreeSet<Studentdemo> set =new TreeSet<Studentdemo>(new sortByName());//做一個比較器,person的子類都能比較
set.add(new Studentdemo("aja", 11));
set.add(new Studentdemo("aja1", 12));
set.add(new Studentdemo("aja3", 1));
set.add(new Studentdemo("aja22", 10));
Iterator<Studentdemo> it =set.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//只要是person 的子類或是自己類,都可以通過(new sortByName())進行比較。這就是下限 ? super E
}
}
class Person implements Comparable<Person>{
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int compareTo(Person o) {
return this.age-o.age;
}
}
class Studentdemo extends Person{
String name;
int age;
public Studentdemo(String name,int age){
super(name,age);
}
}
//TreeSet中的按名字比較的比較器(persom)通用。
class sortByName implements Comparator<Person>{
public int compare(Person o1, Person o2) {
return o1.toString().compareTo(o2.toString());
}
}
相關文章
- java 基礎 泛型Java泛型
- Java基礎-泛型Java泛型
- 【Java基礎】泛型Java泛型
- 【Java反射】Java 泛型基礎Java反射泛型
- java-基礎-泛型Java泛型
- Java基礎-泛型詳解Java泛型
- java基礎複習-----泛型Java泛型
- Java基礎之泛型方法Java泛型
- Java基礎——深入理解泛型Java泛型
- Java基礎之淺談泛型Java泛型
- 夯實Java基礎系列13:深入理解Java中的泛型Java泛型
- Java基礎系列(三十六):泛型中需要注意的地方Java泛型
- Java 基礎 一文搞懂泛型Java泛型
- java入門基礎學習----泛型Java泛型
- java基礎學習之十三:泛型Java泛型
- JAVA基礎之九-泛型(通用型別)Java泛型型別
- Java中的泛型Java泛型
- JavaSE基礎:泛型Java泛型
- TypeScript基礎--泛型TypeScript泛型
- Java基礎知識掃盲(四)——泛型Java泛型
- 一個小栗子聊聊 JAVA 泛型基礎Java泛型
- Java中的泛型方法Java泛型
- Go泛型基礎使用Go泛型
- Java泛型簡明教程Java泛型
- Go泛型解密:從基礎到實戰的全方位解析Go泛型解密
- Java中基於泛型的交叉型別 - {4Comprehension}Java泛型型別
- 基礎篇:深入解析JAVA泛型和Type型別體系Java泛型型別
- Java 中泛型的協變Java泛型
- Java 中泛型的全面解析Java泛型
- 深入解析Java中的泛型Java泛型
- Java中建立泛型型別的例項Java泛型型別
- Java 中的泛型方法及 FunctionJava泛型Function
- Java 泛型中易混淆的地方Java泛型
- Java 泛型中的萬用字元Java泛型字元
- corejava基礎知識(3)-泛型Java泛型
- C#基礎:泛型委託C#泛型
- C#基礎:泛型的理解和使用C#泛型
- Java中泛型的詳細解析,深入分析泛型的使用方式Java泛型