牛客網Java刷題知識點之泛型概念的提出、什麼是泛型、泛型在集合中的應用、泛型類、泛型方法、泛型接口、泛型限定上限、泛型限定下限、 何時使用上限?泛型限定通配符的體現

 

 

   很少說,直接上乾貨!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爲例,

  更多集合,請見

牛客網Java刷題知識點之Java 集合框架的構成、集合框架中的迭代器Iterator、集合框架中的集合接口Collection、集合框架中的Map集合

 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(大數據躺過的坑)

 

 

 

 

 

 

 

 

 

 

相關文章
相關標籤/搜索