JavaSE--泛型

1)泛型是什么:

是一种未知的数据类型,当我们不知道使用什么数据类型时,可以使用泛型。
泛型也可以看作是一个变量,用来接收数据类型。
E e:Element 元素
T t:Type 类型

2)使用泛型解决的问题:

解决向下转型带来的类转换异常(ClassCastException)。

3)使用泛型的好处:

●避免了类转换的麻烦,存储的是什么类型,取出的就是什么类型。
●把运行期异常提升到了编译期异常。
弊端:不使用泛型时能存储任意类型的数据。(不适用默认则为Object)

public class Test {
    public static void main(String[] args) {
//        show1();
        show2();
    }
        //不使用泛型
        public static void show1() {
            //数组不适用泛型则为默认类型,为Object
            ArrayList list = new ArrayList();
            list.add(1);
            list.add("abc");
            //迭代输出
            Iterator it = list.iterator();
            while (it.hasNext()){
                Object obj = it.next();
                System.out.println(obj);
                //调用String特有的方法,Length获取长度
                //向下转型,会抛出异常,不能把Integer类型转换为String类型
                String s =(String) obj ;
                System.out.println(s.length());
            }
    }
        //使用泛型
        public static void show2(){
            ArrayList<String> list =new ArrayList<>();
            list.add("Aaa");
            list.add("Bbb");
            list.add("Ccc");
            //list.add(123); 报错
            //迭代输出
            for (String str : list){
                System.out.println(str);
            }
        }
}

4)含有泛型的类:

使用泛型后,所有类中属性的类型都是动态设置。即创建对象时是什么类型,泛型就是什么类型。

//含有泛型的类
public class GenericClass <E> {
    public E name;
    public E getName() {
        return name;
    }
    public void setName(E name) {
        this.name = name;
    }
}
public class doMain {
    public static void main(String[] args) {
        GenericClass<String> gc1 = new GenericClass<>();
        gc1.setName("String类型");

        GenericClass<Integer> gc2 = new GenericClass<>();
        gc2.setName(1);
    }
}

如果不使用泛型,我们就只能使用一种数据类型。(Object除外,使用Object则会带来安全隐患问题)

5)含有泛型的方法:

定义在方法的修饰符和返回值之间。
作用:调用方法时,传递什么类型,泛型就是什么类型。
格式:

修饰符 <泛型> 返回值类型 方法名(参数列表(使用泛型)){
	方法体;
	}
public class GenericMethod {
    //含有泛型的方法
    public <T> void method(T t){
        System.out.println(t);
    }
    //含有泛型的静态方法
    public static <S> void method2(S s){
        System.out.println(s);
    }
}
public class doMain {
    public static void main(String[] args) {

        GenericMethod gm = new GenericMethod();
        gm.method(10);
        gm.method("abc");
        gm.method(13);

        GenericMethod.method2("静态方法");
        GenericMethod.method2("2");
    }
}

6)含有泛型的接口:

//含有泛型的接口
interface IGeneric<I> {
    public abstract void method(I i);
}

实现方式一:

实现类继续设置泛型标记。

class IGenericImpl<I> implements IGeneric <I>{
    @Override
    public void method(I i) {
        System.out.println(i);
    }
}

实现方式二:

class IGenericImpl2 implements IGeneric<String>{
    @Override
    public void method(String s) {
        System.out.println(s);
    }
}

一和二的差别:
有没有为子类设置具体的泛型。

public class doMain {
    public static void main(String[] args) {
        IGenericImpl gil = new IGenericImpl();
        gil.method("使用泛型接口的实现类1");
        gil.method(1);

        IGenericImpl2 gil2 = new IGenericImpl2();
        gil2.method("使用泛型接口的实现类2");
    }
}

7)泛型的通配符:

<?>

解决的是参数传递的问题。
只能够接收数据,不能够存储数据。

public class Generic {
    public static void main(String[] args) {
        ArrayList<Integer> list01 =new ArrayList<>();
        list01.add(1);
        list01.add(2);

        ArrayList<String> list02 = new ArrayList<>();
        list02.add("a");
        list02.add("b");

        printArray(list01);
        printArray(list02);

        //它只能够接收数据,不能够存储数据
        //ArrayList<?> list03 = new ArrayList<?>();报错
    }
    //定义一个方法,能遍历所有类型的ArrayList集合。
    //这时候我们不知道ArrayList集合使用什么数据类型,可以用泛型的通配符 ? 来接收数据类型
//    public static void printArray(ArrayList<String> list){
    public static void printArray(ArrayList<?> list){
        Iterator<?> it = list.iterator();
        while (it.hasNext()){
            Object obj =it.next();
            System.out.println(obj);
        }
    }
}

注意:在明确设置一个类为泛型类型时,没有继承关系的概念。

public static void printArray(ArrayList<String> list){
public static void printArray(ArrayList<Object> list){

虽然Object与String类是父子类的关系,但换到泛型中就属于两个完全独立的概念。

通配符的高级使用——受限泛型

●泛型的上限:
格式:类名 <? extends 类 > 对象名,可以在方法声明和参数上使用。
作用:只能够接收该类型及其子类。

●泛型的下限:
格式:类名 <? super 类 > 对象名,可以在方法参数上使用。
作用:只能够接收该类型及其父类。

public class doMain {
    public static void main(String[] args) {
        Collection<Integer> list1 = new ArrayList<>();
        Collection<String> list2 = new ArrayList<>();
        Collection<Number> list3 = new ArrayList<>();
        Collection<Object> list4 = new ArrayList<>();

        getElement1(list1);
        getElement1(list2);//报错
        getElement1(list3);
        getElement1(list4);//报错

        getElement2(list1);//报错
        getElement2(list2);//报错
        getElement2(list3);
        getElement2(list4);
    }

    //泛型的上限:此时的泛型?,必须是Number类或其类型的子类
    public static void getElement1(Collection<? extends Number> coll){}
    //泛型的下限:此时的泛型?,必须是Number类或其类型的父类
    public static void getElement2(Collection<? super Number> coll){}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章