博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java刷题知识点之泛型概念的提出、什么是泛型、泛型在集合中的应用、泛型类、泛型方法、泛型接口、泛型限定上限、泛型限定下限、 什么时候使用上限?泛型限定通配符的体现...
阅读量:7234 次
发布时间:2019-06-29

本文共 16851 字,大约阅读时间需要 56 分钟。

 先来看个泛型概念提出的背景的例子。

 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)abchahah

   以上是运行时期出现问题了。

 

 

  定义了一个List类型的集合,先向其中加入了两个字符串类型的值,随后加入一个Integer类型的值。这是完全允许的,因为此时list默认的类型为Object类型。在之后的循环中,由于忘记了之前在list中也加入了Integer类型的值或其他编码原因,很容易出现类似于//1中的错误。因为编译阶段正常,而运行时会出现“java.lang.ClassCastException”异常。因此,导致此类错误编码过程中不易发现。

   在如上的编码过程中,我们发现主要存在两个问题:

  1.当我们将一个对象放入集合中,集合不会记住此对象的类型,当再次从集合中取出此对象时,改对象的编译类型变成了Object类型,但其运行时类型任然为其本身类型。

  2.因此,//1处取出集合元素时需要人为的强制类型转化到具体的目标类型,且很容易出现“java.lang.ClassCastException”异常。

  那么有没有什么办法可以使集合能够记住集合内元素各类型,且能够达到只要编译时不出现问题,运行时就不会出现“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
al = new ArrayList
(); al.add("abc");//public boolean add(Object obj) al.add("hahah");// al.add(4);//al.add(new Integer(4));//1处 Iterator
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类型数据,或者其它自定义类型数据,但是我们没有办法,只能分别写多个方法处理每种数据类型,因为方法的参数类型不同。有没有一种办法,在方法中传入通用的数据类型,这样不就可以合并代码了吗?泛型的出现就是专门解决这个问题的。

 

 

 

 

使用泛型的好处:

好处:
1、将运行时期的问题ClassCastException转到了编译时期。
2、避免了强制转换的麻烦。

 

<>什么时候用?

  当操作的引用数据类型不确定的时候。就使用<>。将要操作的引用数据类型传入即可.

其实<>就是一个用于接收具体引用数据类型的参数范围。

  里面是引用类型,要么放类名,要么放接口名,要么放数组名。

  在程序中,只要用到了带有<>的类或者接口,就要明确传入的具体引用数据类型 。泛型技术是给编译器使用的技术,用于编译时期。确保了类型的安全。

运行时,会将泛型去掉,生成的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
ts = new TreeSet
(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
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
{ 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
{ 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
{ private QQ q; public QQ getObject(){ return q; } public void setObject(QQ object){ this.q = object; } /** * 将泛型定义在方法上。 * @param str */ public
void show(W str){ System.out.println("show : "+str.toString()); } public void print(QQ str){ System.out.println("print : "+str); } /** * 当方法静态时,不能访问类上定义的泛型。如果静态方法使用泛型,只能将泛型定义在方法上。 * @param obj */ public static
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
tool = new Tool
(); 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
{ 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
in2 = new InterImpl2
(); in2.show(5); }}//泛型接口,将泛型定义在接口上。 interface Inter
{ public void show(T t); } class InterImpl2
implements Inter{ public void show(Q q){ System.out.println("show :"+q); } } class InterImpl implements Inter
{ 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
al = new ArrayList
(); al.add("abc"); al.add("hehe"); ArrayList
al2 = new ArrayList
(); 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
al = new ArrayList
(); al.add(new Person("abc",30)); al.add(new Person("abc4",34)); ArrayList
al2 = new ArrayList
(); al2.add(new Student("stu1",11)); al2.add(new Student("stu2",22)); ArrayList
al3 = new ArrayList
(); 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
al) {//Collection
al = new ArrayList
() Iterator
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
al){ Iterator
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
al1 = new ArrayList
(); al1.add(new Person("abc",30)); al1.add(new Person("abc4",34)); ArrayList
al2 = new ArrayList
(); al2.add(new Student("stu1",11)); al2.add(new Student("stu2",22)); ArrayList
al3 = new ArrayList
(); al3.add(new Worker("stu1",11)); al3.add(new Worker("stu2",22)); ArrayList
al4 = new ArrayList
(); al4.add("abcdeef");// al1.addAll(al4);//错误,类型不匹配。 al1.addAll(al2); al1.addAll(al3); System.out.println(al1.size()); }}/* * 一般在存储元素的时候都是用上限,因为这样取出都是按照上限类型来运算的。不会出现类型安全隐患。 */class MyCollection
{ public void add(E e){ } public void addAll(MyCollection
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
al1 = new TreeSet
(new CompByName()); al1.add(new Person("abc4",34)); al1.add(new Person("abc1",30)); al1.add(new Person("abc2",38)); TreeSet
al2 = new TreeSet
(new CompByName()); al2.add(new Student("stu1",11)); al2.add(new Student("stu7",20)); al2.add(new Student("stu2",22)); TreeSet
al3 = new TreeSet
(); al3.add(new Worker("stu1",11)); al3.add(new Worker("stu2",22)); TreeSet
al4 = new TreeSet
(); al4.add("abcdeef");// al1.addAll(al4);//错误,类型不匹配。// al1.addAll(al2);// al1.addAll(al3);// System.out.println(al1.size()); Iterator
it = al2.iterator(); while(it.hasNext()){ System.out.println(it.next()); } }}/* * class TreeSet
* { * Tree(Comparator
comp); * } * 什么时候用下限呢?通常对集合中的元素进行取出操作时,可以是用下限。 */class CompByName implements Comparator
{ 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
{ 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
{ 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
al1 = new ArrayList
(); al1.add(new Person("abc",30)); al1.add(new Person("abc4",34)); ArrayList
al2 = new ArrayList
(); al2.add(new Person("abc22222",30)); al2.add(new Person("abc42222222",34)); ArrayList
al4 = new ArrayList
(); 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
{ public boolean containsAll(Collection
coll){ return true; }}

 

 

 

 

 

泛型的通配符

  ? 未知类型。

泛型的限定

? extends E: 接收E类型或者E的子类型对象。上限
一般存储对象的时候用。比如 添加元素 addAll.

  ? super E: 接收E类型或者E的父类型对象。 下限。

一般取出对象的时候用。比如比较器。

本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/7574951.html,如需转载请自行联系原作者

你可能感兴趣的文章
Geometry Imager Viewport Filter
查看>>
mysql 批量kill locked 进程
查看>>
Unix 环境高级编程
查看>>
WinForm(VB.NET)获取当前登录的用户名
查看>>
C语言 百炼成钢17
查看>>
分库分表总结
查看>>
正则表达式的优先级
查看>>
利用mvn进行多环境配置
查看>>
JMS发布/订阅消息传送例子
查看>>
Oracle 基础系列之1.2 oracle的基本使用
查看>>
POJ 1149 PIGS (最大流)
查看>>
fitnesse - 一个简单的例子(slim)
查看>>
小白也能懂的手写体识别
查看>>
vs中批量删除注释
查看>>
《程序出错后,程序员给测试人员的20条高频回复》
查看>>
SQL SERVER-时间戳(timestamp)与时间格式(datetime)互相转换
查看>>
JAVA Lambda Expressions streams
查看>>
Mysql性能优化教程
查看>>
printk 与syslog
查看>>
做图像分析的一些感受
查看>>