泛型的学习

在ArrayList的创建里,经常用泛型来创建对象,那么这个泛型的作用是什么呢

起始可以将泛型理解为一种规范,在创建时只要满足这种规范的数据才能被加入ArrayList

例如:

ArrayList<String> arrlist = new ArrayList<>();

这时候<String>表示我这个集合里面只能被放入String类型的数据

带泛型的方法

但是我能不能在创建方法时,创建一个带泛型的方法,在调用方法的时候再确定需要传入该方法的数据的数据类型呢,这个时候就需要用到泛型

下列为一个创建泛型的方法代码:

这个方法没有限制一定需要传入的方法中参数的类型,而是在方法的调用的时候才确定具体调用方法的类型。

package com.itazhang.demo1;

import java.util.ArrayList;

public  class Test9 {
    public static <E> void addAll(ArrayList<E> list1,E a1, E a2){
        list1.add(a1);
        list1.add(a2);
    }
}

下列为具体方法调用时泛型的使用

这个时候我使用这个方法时候传入的是<String>类型的参数,所以这个时候上面类里的方法会自动将需要传入参数的类型变为String,假如我这里传入的是<Integer>类型,上面的类就会将需要传入的参数类型自动改为<Integer>类型

package com.itazhang.demo1;

import java.util.ArrayList;

public class Test10 {
    public static void main(String[] args) {
        ArrayList<String> arrlist = new ArrayList<>();
        Test9.addAll(arrlist,"aaa","bbb");
        System.out.println(arrlist.toString());
    }
}

但注意,带泛型的方法只能在本方法使用,在其他的方法体中无法使用

带泛型的类

如果用带泛型的类的话,那么该类里的所有方法都能用带泛型的方法,也就是上诉定义方法的格式来使用带泛型的方法。

带泛型的接口

如果我使用接口的话,我不知道我后面创建实例化对象的时候需要传递的参数类型,这个时候就可以使用带泛型的接口。

public class MyArraList<E> implements List<E>

例如上诉代码,我的这个类使用接口时我定义一个带泛型的接口,这个时候我创建这个类的实例化对象并使用这个类里的方法时候,创建什么类型的参数,这个接口就会提供什么类型的方法

实现如下:

这是使用泛型来处理这个接口的类型

package com.itazhang.demo2;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class MyArraList<E> implements List<E> {
    @Override
    public int size() {
        return 0;
    }

    @Override
    public boolean isEmpty() {
        return false;
    }

    @Override
    public boolean contains(Object o) {
        return false;
    }

    @Override
    public Iterator<E> iterator() {
        return null;
    }

    @Override
    public Object[] toArray() {
        return new Object[0];
    }

    @Override
    public <T> T[] toArray(T[] a) {
        return null;
    }

    @Override
    public boolean add(E e) {
        return false;
    }

    @Override
    public boolean remove(Object o) {
        return false;
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        return false;
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        return false;
    }

    @Override
    public boolean addAll(int index, Collection<? extends E> c) {
        return false;
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        return false;
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        return false;
    }

    @Override
    public void clear() {

    }

    @Override
    public E get(int index) {
        return null;
    }

    @Override
    public E set(int index, E element) {
        return null;
    }

    @Override
    public void add(int index, E element) {

    }

    @Override
    public E remove(int index) {
        return null;
    }

    @Override
    public int indexOf(Object o) {
        return 0;
    }

    @Override
    public int lastIndexOf(Object o) {
        return 0;
    }

    @Override
    public ListIterator<E> listIterator() {
        return null;
    }

    @Override
    public ListIterator<E> listIterator(int index) {
        return null;
    }

    @Override
    public List<E> subList(int fromIndex, int toIndex) {
        return null;
    }
}

下面是定义一个该类的String类型的对象

package com.itazhang.demo2;

public class Test1 {
    public static void main(String[] args) {
        MyArraList<String> list1 = new MyArraList<>();
        list1.add("aaa");
    }
}

可以看出,因为我创建的是一个String类型的对象,所有这个接口会自动给我提供传递String类型参数的方法,而当我创建的是一个<Integer>类型的对象时,根据这个类型,这个接口也一定会提供一个传递参数为<Integer>类型的方法。这就是带泛型接口使用起来的好处。

通配符

在上述见识到了泛型的好处,那么有一个问题,我只有一些类才想能使用带有泛型的方法,而其他类我不想让她使用怎么办呢,这个时候就需要泛型的通配符

格式:

<? extends 类名>

表示只有这个类的子类和他自己才能用,换句话说只有他自己或者直接继承或间接继承该类的子类们才能用

<? super 类名>

表示只有这个类的父类和他自己才能用,换句话说只有他自己或者他的父类以及间接父类才能使用

如下:这个时候只有GrandFather的子类或间接子类才能使用add1方法

package com.itazhang.demo2;

import java.util.ArrayList;

public class Test1 {
    public static void main(String[] args) {
        ArrayList <Father>a = new ArrayList<>();
        ArrayList <GrandFather>b = new ArrayList<>();
        ArrayList <Son>c = new ArrayList<>();
        ArrayList <Gg>d = new ArrayList<>();
        add1(a);
        add1(b);
        add1(c);

    }
    public static void add1(ArrayList<? extends GrandFather>list){
        System.out.println("我是一个测试方法");
    }
}
class Father extends GrandFather{}
class GrandFather{}
class Son extends Father{}
class Gg{}

假如我要用一个不是GrandFather的子类对象使用add1方法时就会报错,如下:

下列为一个相关练习,要求如下:

代码如下,具体相关类的创建省略,只给出测试类和相关结果

package com.itazhang.demo2.Exercise;

import java.util.ArrayList;

public class Exercise1 {
    public static void main(String[] args) {
        ArrayList<Animal> animals = new ArrayList<>();
        ArrayList<Cat> cats = new ArrayList<>();
        Hua cat1 = new Hua();
        Boss cat2 = new Boss();
        animals.add(cat1);
        animals.add(cat2);
        cats.add(cat1);
        cats.add(cat2);
        keepCat(cats);
        System.out.println("---------1----------");
        ArrayList<Dog> dogs = new ArrayList<>();
        Hasaky dog1 =new Hasaky();
        Tiddy dog2 = new Tiddy();
        animals.add(dog1);
        animals.add(dog2);
        dogs.add(dog1);
        dogs.add(dog2);
        keepDog(dogs);
        System.out.println("-----------2-----------");
        keepAnimal(animals);
    }
    //打印猫的方法
    public static void keepCat(ArrayList<? extends Cat> list){
        for (int i = 0; i < list.size(); i++) {
            list.get(i).eat();
        }
    }
    public static void keepDog(ArrayList<? extends Dog> list){
        for (int i = 0; i < list.size(); i++) {
            list.get(i).eat();
        }
    }
    public static void keepAnimal(ArrayList<? extends Animal> list){
        for (int i = 0; i < list.size(); i++) {
            list.get(i).eat();
        }
    }
}

运行结果如下:

  • 22
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值