java泛型详解

泛型
泛型技术:是给编译器使用的技术,编译器进行类型安全检查。将运行时发生的不可解决的异常,在编译检查时期就 制止住。
< 参数 > 也相当于传参数,E也是变量,相当于把类型传进去进行一个限定。
案例

public class GenericTest {
public static void main(String[]args)
{
Set set=new TreeSet(new Comparator() {
@Override
public int compare(String o1, String o2) {
int temp=o1.length()-o2.length();//第一比较条件
return temp==0?o1.compareTo(o2):temp;
}
});
set.add(“adadaw”);
set.add(“adada”);
set.add(“zkzks”);
set.add(“bsdw”);
for (Iterator iterator=set.iterator();iterator.hasNext()😉 {
System.out.println(iterator.next());
}
}
}
泛型.脱离集合
1.泛型类
自定义泛型类——最大的便利,对传入的变量类型进行限制,跟集合一样。
泛型类型用于类的定义中,被称为泛型类。通过泛型可以完成对一组类的操作对外开放相同的接口。最典型的就是各种容器类,如:List、Set、Map。

泛型类的最基本写法(这么看可能会有点晕,会在下面的例子中详解):

class 类名称 <泛型标识:可以随便写任意标识号,标识指定的泛型的类型>
{ private 泛型标识 /*(成员变量类型)*/ var; ..... } }
一个最普通的泛型类:

//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
//在实例化泛型类时,必须指定T的具体类型
public class Generic<T>{ 
    //key这个成员变量的类型为T,T的类型由外部指定  
    private T key;
    public Generic(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定
        this.key = key;
    }
    public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
        return key;
    }
}
 

//泛型的类型参数只能是类类型(包括自定义类),不能是简单类型
//传入的实参类型需与泛型的类型参数类型相同,即为Integer.
Generic<Integer> genericInteger = new Generic<Integer>(123456);
//传入的实参类型需与泛型的类型参数类型相同,即为String.
Generic<String> genericString = new Generic<String>("key_vlaue");
Log.d("泛型测试","key is " + genericInteger.getKey());
Log.d("泛型测试","key is " + genericString.getKey());
 

12-27 09:20:04.432 13063-13063/? D/泛型测试: key is123456 
12-27 09:20:04.432 13063-13063/? D/泛型测试: key is key_vlaue

定义的泛型类,就一定要传入泛型类型实参么?并不是这样,在使用泛型的时候如果传入泛型实参,则会根据传入的泛型实参做相应的限制,此时泛型才会起到本应起到的限制作用。如果不传入泛型类型实参的话,在泛型类中使用泛型的方法或成员变量定义的类型可以为任何的类型。

看一个例子:

Generic generic = new Generic("111111");
Generic generic1 = new Generic(4444);
Generic generic2 = new Generic(55.55);
Generic generic3 = new Generic(false);
Log.d("泛型测试","key is " + generic.getKey());
Log.d("泛型测试","key is " + generic1.getKey());
Log.d("泛型测试","key is " + generic2.getKey());
Log.d("泛型测试","key is " + generic3.getKey());
D/泛型测试: key is 111111
D/泛型测试: key is 4444
D/泛型测试: key is 55.55
D/泛型测试: key is false

注意:

泛型的类型参数只能是类类型,不能是简单类型。
不能对确切的泛型类型使用instanceof操作。如下面的操作是非法的,编译时会出错。

if(ex_num instanceof Generic){ }

2.泛型方法

当成员方法要操作不确定类型并且和泛型类限制的类型不一样时,就可以使用泛型方法。
(妈的图片掉了)

Community Edition 2019.1\bin" -Dfile.encoding=UTF-8 -classpath G:\测试\out\production\测试 GenericTest
show123
showduiahiuw
showjava.lang.Exception
printwocoanima

小知识点:

class Tool<w>
{
    public <q> void show(q q1)//泛型方法
    {
        System.out.println("show"+q1);
    }
    public static void print(w w1)
    {
        System.out.println("print"+w1);
    }
}

泛型w,只有在创建对象时才会被引入,而静态编译时就就要加载。

3.泛型接口

public class GenericTest {
    public static void main(String[]args)
    {
        new InterDemo2<String>().show("hadkdhkuwhd");
        new InterDemo().show("isjdiuahwu");
    }
}
interface Inter<E>
{
    public void show(E e);
}
class InterDemo implements Inter<String>
{
    @Override
    public void show(String s) {
        System.out.println(s);
    }
}
class InterDemo2<T> implements Inter<T>
{
    @Override
    public void show(T t) {
        System.out.println(t);
    }
}

3.泛型通配符号<?>

在集合中我们经常会用到这样
比如我们有多个集合,而且每个集合都想迭代出元素,并且进行操作
所以我们可以将迭代方法封装起来,进行调用
class Person
{
    ......
}
class worker extends Person
{......}
class student extends Person
{
......
}
Set<worker> set=new HashSet<worker>();
set.add(new worker("nimei"));
set.add(new worker("wocao"));
Set<student> set2=new HashSet<student>();
set2.add(new student("worinia"));
set2.add(new student("dkahdku"));
当传入的具体参数类型不确定,可以使用通配符<?>
注意这里写的是Collection集合,说明,它可以接受Collection的所有子类型
private static void PrintList(Collection<?> set)
{
    for(Iterator<?> it=set.iterator();it.hasNext())
    {
        System.out.print(it.Next().toString());
    }
}

4.泛型的限定

<? extends OBject>=<?>
所以,我们有要求,就是传入集合的参数类型,除了worker,和student不能有其他的的类型
那我们就要对集合进行跟深一步的限定了
找到worker和student的共性:
那就是共同的爹->Person类
private static void PrintList(Collection<? extends Person> set)
{
    for(Iterator<? extends Person> it=set.iterator();it.hasNext())
    {
        Person p=it.Next();//向上转型
        System.out.print(p.getName());//Person的特有方法。
    }
}
? super E:接受E类型以及E的父类   上限
? extends E:接受E类型以及E的子类  下限
private static void PrintList(Collection<Person> set)

这样写是不行的哦,这里的Person已经是一个具体的类型,是一个 Person的类型,虽然它跟worker和student有继承关系,但是照样不能接受worker和student
但是不能这样写,不然也会报错。

上限和下限相当于是对通配符的限定。

4.1)泛型限定在API的应用

TreeSet(Collection<? extends E> c)

TreeSet(Comparator<? super E> comparator)

class Person implements Comparable<Person>//比较Person ,要想放入TreeSet首先你得具有比较性
{
    ......
        @override
        public int compareTo(Person o)
    {
        int temp=this.age-o.age;
        return temp==0?this.name.compareTo(o.name):temp;
    }
}
class worker extends Person
{......}
class student extends Person
{
......
}
Collection<Student> c=new ArrarList<Student>();
c.add("lisi1",20);
c.add("lisi2",30);

TreeSet se=new TreeSet(Collection<? extends Person> c);//这样就能将集合c的元素添加到se中,并且利用TreeSet特性,进行排序
se.add(“wocaonima”,25);
新需求,利用worker和student的共性,只需要创建一个父类person公共比较器comparator
这样既可以比较worker的内容也可以比较student的内容了。

class TreeSet<E>
      TreeSet<E>(new Comparator<E> e){};
TreeSet<student> se=new TreeSet<student>(new Comparator<? super student>());
class CompareByName implements Comparator<person>//创建person的比较器
{
   public int compare(person p1,person p2)
   {
   int temp=p1.getName().compareTo(p2.getName());
   return temp==0?p1.getAge()-p2.getAge():temp;
   }
}

4.2)泛型限定的应用案例 :获取集合中的最大值。

public static <T extends Comparable<? super T>> T getMax(Collection<? extends T> c)
{
    Iterator<? extends T> it=c.iterator();
    T max=it.next();
    while(it.hasNext())
    {
        T temp=it.next();
        if(temp.compareTo(max)>0)
        {
            max=temp;
        }
    }
}

分析这个函数
参数是Collection<? extends T> c,传入的是一个集合,泛型限定的是T以及它的子类
<T extends Comparable<? super T>>,是这个静态函数的限定,T继承comparable说明,它具有compareTo()函数,并且必须是继承了comparable的才能传进来,不然不能传入函数,在编译时期就会报错!! 不过这个方法是T的父类的以及写好的,所以这个函数牛逼在,它不仅可以接受T以及它的子类,并且按照规定返回最大那一个,还通过T父类的compareTo()来判断。
通用了!!!

5.Collections工具类

这个类的方法全部都是静态。
Collections.max(collection c)//根据其元素的 自然顺序返回给定集合的最大元素。
Collections.max(collection c,new comparator())//根据指定的比较器引发的顺序返回给定集合的最大元素。
Collections.min(collection c)
Collections.min(collection c,new comparator())
Collections.sort(List list)//将集合自然排序
Collections.sort(List list, Comparator<? super T> c)
Collections.swap(List<?> list, int i, int j)

        以上所有带有比较器参数的函数都可以自定义比较器然后进行调用比如
Collections.sort(List<T> list, new comparebylength());
class comparebylength implements comparator<string>
{
public compare(string t1,string t2)
{
int temp=t1.length-t2.length;
return temp==0?t1.compareTo(t2):temp;
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值