很少說,直接上乾貨!html
先來看個泛型概念提出的背景的例子。java
GenericDemo.java數組
package zhouls.bigdata.DataFeatureSelection; import java.util.ArrayList; import java.util.Iterator; public class GenericDemo { /** * @param args */ public static void main(String[] args) { ArrayList al = new ArrayList(); al.add("abc");//public boolean add(Object obj) al.add("hahah"); al.add(4);//al.add(new Integer(4)); Iterator it = al.iterator(); while(it.hasNext()){ String str = (String)it.next();//1處 System.out.println(str); } } }
輸出安全
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at zhouls.bigdata.DataFeatureSelection.GenericDemo.main(GenericDemo.java:20) abc hahah
以上是運行時期出現問題了。微信
定義了一個List類型的集合,先向其中加入了兩個字符串類型的值,隨後加入一個Integer類型的值。這是徹底容許的,由於此時list默認的類型爲Object類型。在以後的循環中,因爲忘記了以前在list中也加入了Integer類型的值或其餘編碼緣由,很容易出現相似於//1中的錯誤。由於編譯階段正常,而運行時會出現「java.lang.ClassCastException」異常。所以,致使此類錯誤編碼過程當中不易發現。框架
在如上的編碼過程當中,咱們發現主要存在兩個問題:機器學習
1.當咱們將一個對象放入集合中,集合不會記住此對象的類型,當再次從集合中取出此對象時,改對象的編譯類型變成了Object類型,但其運行時類型任然爲其自己類型。ide
2.所以,//1處取出集合元素時須要人爲的強制類型轉化到具體的目標類型,且很容易出現「java.lang.ClassCastException」異常。post
那麼有沒有什麼辦法可使集合可以記住集合內元素各種型,且可以達到只要編譯時不出現問題,運行時就不會出現「java.lang.ClassCastException」異常呢?答案就是使用泛型。學習
再次修改,GenericDemo.java
這就是,將運行時期的問題ClassCastException轉到了編譯時期。
再次修改,GenericDemo.java
package zhouls.bigdata.DataFeatureSelection; import java.util.ArrayList; import java.util.Iterator; public class GenericDemo { /** * @param args */ public static void main(String[] args) { ArrayList<String> al = new ArrayList<String>(); al.add("abc");//public boolean add(Object obj) al.add("hahah"); // al.add(4);//al.add(new Integer(4));//1處 Iterator<String> it = al.iterator(); while(it.hasNext()){ String str = it.next();//2處 System.out.println(str); } } }
採用泛型寫法後,在//1處想加入一個Integer類型的對象時會出現編譯錯誤,經過List<String>,直接限定了list集合中只能含有String類型的元素,從而在//2處無須進行強制類型轉換,由於此時,集合可以記住元素的類型信息,編譯器已經可以確認它是String類型了。
結合上面的泛型定義,咱們知道在List<String>中,String是類型實參,也就是說,相應的List接口中確定含有類型形參。且get()方法的返回結果也直接是此形參類型(也就是對應的傳入的類型實參)。
什麼是泛型?
泛型:jdk1.5出現的安全機制。
咱們在編寫程序時,常常遇到兩個模塊的功能很是類似,只是一個是處理int型數據,另外一個是處理String類型數據,或者其它自定義類型數據,可是咱們沒有辦法,只能分別寫多個方法處理每種數據類型,由於方法的參數類型不一樣。有沒有一種辦法,在方法中傳入通用的數據類型,這樣不就能夠合併代碼了嗎?泛型的出現就是專門解決這個問題的。
使用泛型的好處:
好處:
一、將運行時期的問題ClassCastException轉到了編譯時期。
二、避免了強制轉換的麻煩。
<>何時用?
當操做的引用數據類型不肯定的時候。就使用<>。將要操做的引用數據類型傳入便可.
其實<>就是一個用於接收具體引用數據類型的參數範圍。
裏面是引用類型,要麼放類名,要麼放接口名,要麼放數組名。
在程序中,只要用到了帶有<>的類或者接口,就要明確傳入的具體引用數據類型 。泛型技術是給編譯器使用的技術,用於編譯時期。確保了類型的安全。
運行時,會將泛型去掉,生成的class文件中是不帶泛型的,這個稱爲泛型的擦除。
爲何擦除呢?由於爲了兼容運行的類加載器。
泛型的補償:在運行時,經過獲取元素的類型進行轉換動做。不用使用者在強制轉換了。
泛型在集合中的應用
我這裏僅僅以集合中的TreeSet爲例,
更多集合,請見
GenericDemo.java
package zhouls.bigdata.DataFeatureSelection; import java.util.Iterator; import java.util.TreeSet; import zhouls.bigdata.DataFeatureSelection.Person; import zhouls.bigdata.DataFeatureSelection.ComparatorByName; public class GenericDemo { /** * @param args */ public static void main(String[] args) { TreeSet<Person> ts = new TreeSet<Person>(new ComparatorByName()); ts.add(new Person("lisi8",21)); ts.add(new Person("lisi3",23)); ts.add(new Person("lisi",21)); ts.add(new Person("lis0",20)); Iterator<Person> it = ts.iterator(); while(it.hasNext()){ Person p = it.next(); System.out.println(p.getName()+":"+p.getAge()); } } }
由於TreeSet是須要是二叉樹,須要進行比較排序。
Person.java
package zhouls.bigdata.DataFeatureSelection; public class Person implements Comparable<Person> { private String name; private int age; public Person() { super(); } public Person(String name, int age) { super(); this.name = name; this.age = age; } public int compareTo(Person p){ // Person p = (Person)obj; int temp = this.age - p.age; return temp==0?this.name.compareTo(p.name):temp; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } 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 String toString() { return "Person:"+getName()+":"+getAge(); } }
ComparatorByName.java
package zhouls.bigdata.DataFeatureSelection; import java.util.Comparator; import zhouls.bigdata.DataFeatureSelection.Person; public class ComparatorByName implements Comparator<Person> { public int compare(Person o1, Person o2) { int temp = o1.getName().compareTo(o2.getName()); return temp==0? o1.getAge()-o2.getAge(): temp; } }
什麼是泛型類?何時用泛型類?泛型類?
在jdk1.5後,使用泛型來接收類中要操做的引用數據類型。
泛型類。何時用?當類中的操做的引用數據類型不肯定的時候,就使用泛型來表示。
Tool.java
package zhouls.bigdata.DataFeatureSelection; /* public class Tool { private Object object; public Object getObject() { return object; } public void setObject(Object object) { this.object = object; } } */ //在jdk1.5後,使用泛型來接收類中要操做的引用數據類型。 //泛型類。何時用?當類中的操做的引用數據類型不肯定的時候,就使用泛型來表示。 public class Tool<QQ>{ private QQ q; public QQ getObject(){ return q; } public void setObject(QQ object){ this.q = object; } /** * 將泛型定義在方法上。 * @param str */ public <W> void show(W str){ System.out.println("show : "+str.toString()); } public void print(QQ str){ System.out.println("print : "+str); } /** * 當方法靜態時,不能訪問類上定義的泛型。若是靜態方法使用泛型,只能將泛型定義在方法上。 * @param obj */ public static <Y> void method(Y obj){ System.out.println("method:"+obj); } }
GenericDefineDemo.java
package zhouls.bigdata.DataFeatureSelection; import zhouls.bigdata.DataFeatureSelection.Student; import zhouls.bigdata.DataFeatureSelection.Worker; public class GenericDefineDemo{ /** * @param args */ public static void main(String[] args){ Tool<String> tool = new Tool<String>(); tool.show(new Integer(4));//show : 4 tool.show("abc");//show : abc tool.print("hahah");//print : hahah // tool.print(new Integer(8));//不能 Tool.method("haha");//method:haha Tool.method(new Integer(9));//method:9 } }
Student.java
package zhouls.bigdata.DataFeatureSelection; public class Student extends Person{ public Student(){ super(); } public Student(String name, int age){ super(name, age); } @Override public String toString(){ return "Student:"+getName()+":"+getAge(); } }
Worker.java
package zhouls.bigdata.DataFeatureSelection; public class Worker extends Person{ public Worker(){ super(); } public Worker(String name, int age){ super(name, age); } @Override public String toString(){ return "Worker:"+getName()+":"+getAge(); } }
Person.java
package zhouls.bigdata.DataFeatureSelection; public class Person implements Comparable<Person> { private String name; private int age; public Person() { super(); } public Person(String name, int age) { super(); this.name = name; this.age = age; } public int compareTo(Person p){ // Person p = (Person)obj; int temp = this.age - p.age; return temp==0?this.name.compareTo(p.name):temp; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } 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 String toString() { return "Person:"+getName()+":"+getAge(); } }
泛型接口
GenericDefineDemo.java
package zhouls.bigdata.DataFeatureSelection; public class GenericDefineDemo { /** * @param args */ public static void main(String[] args) { InterImpl in = new InterImpl(); in.show("abc"); InterImpl2<Integer> in2 = new InterImpl2<Integer>(); in2.show(5); } } //泛型接口,將泛型定義在接口上。 interface Inter<T>{ public void show(T t); } class InterImpl2<Q> implements Inter<Q>{ public void show(Q q){ System.out.println("show :"+q); } } class InterImpl implements Inter<String>{ public void show(String str){ System.out.println("show :"+str); } }
泛型限定上限
GenericAdvanceDemo.java
package zhouls.bigdata.DataFeatureSelection; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; public class GenericAdvanceDemo { /** * @param args */ public static void main(String[] args) { ArrayList<String> al = new ArrayList<String>(); al.add("abc"); al.add("hehe"); ArrayList<Integer> al2 = new ArrayList<Integer>(); al2.add(5); al2.add(67); printCollection(al); printCollection(al2); } /** * 迭代並打印集合中元素。 * @param al */ public static void printCollection(Collection<?> al) { Iterator<?> it = al.iterator(); while(it.hasNext()){ System.out.println(it.next().toString()); } } }
泛型限定下限
GenericAdvanceDemo.java
package zhouls.bigdata.DataFeatureSelection; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import zhouls.bigdata.DataFeatureSelection.Person; import zhouls.bigdata.DataFeatureSelection.Student; import zhouls.bigdata.DataFeatureSelection.Worker; public class GenericAdvanceDemo { /** * @param args */ public static void main(String[] args) { ArrayList<Person> al = new ArrayList<Person>(); al.add(new Person("abc",30)); al.add(new Person("abc4",34)); ArrayList<Student> al2 = new ArrayList<Student>(); al2.add(new Student("stu1",11)); al2.add(new Student("stu2",22)); ArrayList<String> al3 = new ArrayList<String>(); al3.add("stu3331"); al3.add("stu33332"); printCollection(al2); printCollection(al); } /** * 迭代並打印集合中元素。 * * 能夠對類型進行限定: * ? extends E:接收E類型或者E的子類型對象。上限! * * ? super E :接收E類型或者E的父類型。下限! * @param al */ /*public static void printCollection(Collection<? extends Person> al) {//Collection<Dog> al = new ArrayList<Dog>() Iterator<? extends Person> it = al.iterator(); while(it.hasNext()){ // T str = it.next(); // System.out.println(str); // System.out.println(it.next().toString()); Person p = it.next(); System.out.println(p.getName()+":"+p.getAge()); } }*/ public static void printCollection(Collection<? super Student> al){ Iterator<? super Student> it = al.iterator(); while(it.hasNext()){ System.out.println(it.next()); } } }
何時使用上限?
GenericAdvanceDemo.java
package zhouls.bigdata.DataFeatureSelection; import java.util.ArrayList; import zhouls.bigdata.DataFeatureSelection.Person; import zhouls.bigdata.DataFeatureSelection.Student; import zhouls.bigdata.DataFeatureSelection.Worker; public class GenericAdvanceDemo{ /** * @param args */ public static void main(String[] args) { ArrayList<Person> al1 = new ArrayList<Person>(); al1.add(new Person("abc",30)); al1.add(new Person("abc4",34)); ArrayList<Student> al2 = new ArrayList<Student>(); al2.add(new Student("stu1",11)); al2.add(new Student("stu2",22)); ArrayList<Worker> al3 = new ArrayList<Worker>(); al3.add(new Worker("stu1",11)); al3.add(new Worker("stu2",22)); ArrayList<String> al4 = new ArrayList<String>(); al4.add("abcdeef"); // al1.addAll(al4);//錯誤,類型不匹配。 al1.addAll(al2); al1.addAll(al3); System.out.println(al1.size()); } } /* * 通常在存儲元素的時候都是用上限,由於這樣取出都是按照上限類型來運算的。不會出現類型安全隱患。 */ class MyCollection<E>{ public void add(E e){ } public void addAll(MyCollection<? extends E> e){ } }
何時使用下限?
GenericAdvanceDemo.java
package zhouls.bigdata.DataFeatureSelection; import java.util.Comparator; import java.util.Iterator; import java.util.TreeSet; import zhouls.bigdata.DataFeatureSelection.Person; import zhouls.bigdata.DataFeatureSelection.Student; import zhouls.bigdata.DataFeatureSelection.Worker; public class GenericAdvanceDemo { /** * @param args */ public static void main(String[] args) { TreeSet<Person> al1 = new TreeSet<Person>(new CompByName()); al1.add(new Person("abc4",34)); al1.add(new Person("abc1",30)); al1.add(new Person("abc2",38)); TreeSet<Student> al2 = new TreeSet<Student>(new CompByName()); al2.add(new Student("stu1",11)); al2.add(new Student("stu7",20)); al2.add(new Student("stu2",22)); TreeSet<Worker> al3 = new TreeSet<Worker>(); al3.add(new Worker("stu1",11)); al3.add(new Worker("stu2",22)); TreeSet<String> al4 = new TreeSet<String>(); al4.add("abcdeef"); // al1.addAll(al4);//錯誤,類型不匹配。 // al1.addAll(al2); // al1.addAll(al3); // System.out.println(al1.size()); Iterator<Student> it = al2.iterator(); while(it.hasNext()){ System.out.println(it.next()); } } } /* * class TreeSet<Worker> * { * Tree(Comparator<? super Worker> comp); * } * 何時用下限呢?一般對集合中的元素進行取出操做時,能夠是用下限。 */ class CompByName implements Comparator<Person>{ public int compare(Person o1, Person o2) { int temp = o1.getName().compareTo(o2.getName()); return temp==0? o1.getAge()-o2.getAge():temp; } } class CompByStuName implements Comparator<Student>{ public int compare(Student o1, Student o2) { int temp = o1.getName().compareTo(o2.getName()); return temp==0? o1.getAge()-o2.getAge():temp; } } class CompByWorkerName implements Comparator<Worker>{ public int compare(Worker o1, Worker o2) { int temp = o1.getName().compareTo(o2.getName()); return temp==0? o1.getAge()-o2.getAge():temp; } }
泛型限定通配符的體現
GenericAdvanceDemo.java
package zhouls.bigdata.DataFeatureSelection; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; import java.util.TreeSet; import zhouls.bigdata.DataFeatureSelection.Person; import zhouls.bigdata.DataFeatureSelection.Student; import zhouls.bigdata.DataFeatureSelection.Worker; public class GenericAdvanceDemo { /** * @param args */ public static void main(String[] args) { ArrayList<Person> al1 = new ArrayList<Person>(); al1.add(new Person("abc",30)); al1.add(new Person("abc4",34)); ArrayList<Person> al2 = new ArrayList<Person>(); al2.add(new Person("abc22222",30)); al2.add(new Person("abc42222222",34)); ArrayList<String> al4 = new ArrayList<String>(); al4.add("abcdeef"); al4.add("abc"); al1.containsAll(al4); // "abc".equals(new Person("ahahah",20)); } public static void printCollection(Collection<?> al){ Iterator<?> it = al.iterator(); while(it.hasNext()){ System.out.println(it.next().toString()); } } } class MyCollection2<E>{ public boolean containsAll(Collection<?> coll){ return true; } }
泛型的通配符:
? 未知類型。
泛型的限定:
? extends E: 接收E類型或者E的子類型對象。上限
通常存儲對象的時候用。好比 添加元素 addAll.
? super E: 接收E類型或者E的父類型對象。 下限。
通常取出對象的時候用。好比比較器。
同時,你們能夠關注個人我的博客:
http://www.cnblogs.com/zlslch/ 和 http://www.cnblogs.com/lchzls/
詳情請見:http://www.cnblogs.com/zlslch/p/7473861.html
人生苦短,我願分享。本公衆號將秉持活到老學到老學習無休止的交流分享開源精神,匯聚於互聯網和我的學習工做的精華乾貨知識,一切來於互聯網,反饋回互聯網。
目前研究領域:大數據、機器學習、深度學習、人工智能、數據挖掘、數據分析。 語言涉及:Java、Scala、Python、Shell、Linux等 。同時還涉及日常所使用的手機、電腦和互聯網上的使用技巧、問題和實用軟件。 只要你一直關注和呆在羣裏,天天必須有收穫
以及對應本平臺的QQ羣:161156071(大數據躺過的坑)