Java基础复习—泛型

一、泛型的概念及意义

我对于泛型的理解就是在一种形式类型,可以类比于形式参数。

它的作用是在我们不清楚具体的类型时,做的一种形式定义。并且在这种定义下可以进行多种类型的定义。

二、泛型的作用域

泛型可以作用于:1.类 2.接口 3.方法;

1.泛型类

泛型类中最经典的就是各种容器类:set、list、map;
在这些类中提供了对不同类型的相同方法。

泛型类是在实例化类的时候指定泛型的具体类型;
下面定义一个简单的泛型类;

class demo<T>{
	//定义一个T类型的变量;
	private <T> a;
	//利用构造器把传入的T类型变量赋值给a;
	demo(T x){
		a = x;
	}
	//将a的值返回;
	public T geta(){
		return a;
	}
}

public class test{
	public static void main(String[] args){
		//没有为泛型类中的泛型传入实参
		demo d1 = new demo();
		//利用使用泛型的方法
		demo<Integer> d2 = new demo<>(123);
		int a = d2.geta();
	}
}

在定义泛型类的派生类时不能继续使用泛型参数;

//例如这段代码就是错误的
class ext extends base<T>{}

可以使用一下方式定义派生类

//为泛型参数指定具体的实参;
class ext extends base<String>{}
//不带泛型定义的父类;
class ext extends base{}

2.泛型接口

泛型接口基本与泛型类一致;
下面定义一个简单的泛型接口

interface test<T>{
	public <T> print(){}
}

class demo implements test<T>{
	@override
	public <T> print(){
	return null;
	}
}

3.泛型方法

在调用泛型方法的时候指定泛型的具体类型;

扫描二维码关注公众号,回复: 5789264 查看本文章

在fun1中是将一个泛型数组的元素添加到泛型集合中。
此时的泛型参数只需要是具有父子关系则不会出现异常。

在fun2中是将一个泛型集合的元素复制给另个集合。
此时的泛型参数只需要是具有父子关系则不会出现异常。
而在fun2中对于collection< T >来说只有T的类型完全相同才能复制。
所以我们利用了类型通配符并且设定了上限。
从而使得T类型的子类都可以复制给c2集合。

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;

public class demo {

    static <T> void fun1(T[] obj, Collection<T> collection) {
        for (T o :
                obj) {
            collection.add(o);
        }
        for (T O :
                collection) {
            System.out.println(O);
        }
    }

    static <T> void fun2(Collection<? extends T> c1, Collection<T> c2) {
        for (T obj:
             c1) {
            c2.add(obj);
        }
        for (T obj:
             c2) {
            System.out.println(obj);
        }
    }

    public static void main(String[] args) {
        Collection<String> c1 = new ArrayList<>();
        String[] strarr = new String[]{"1", "2", "3"};
        //调用fun函数将strarr字符串数组中的元素添加到c1集合中
        //fun1(strarr,c1);

        Collection<Object> i1 = new HashSet<>();
        Integer[] ints = new Integer[]{4, 5, 6};
        //调用fun函数将ints的整形数组添加到i1的Object类型的集合中
        //对于类型T来说只要是有父子接口实现关系就可进行使用;
        //fun1(ints, i1);

        ArrayList<String> list1 = new ArrayList<>();
        ArrayList<Object> list2 = new ArrayList<>();
        for (int i = 1; i <= 3; i++) {
            String s = String.valueOf(i);
            list1.add(s);
        }
        //将String类型的集合元素复制给Object类型的集合
        fun2(list1,list2);

    }
}

三、泛型通配符

类型通配符一般是使用?代替具体的类型实参,注意了,此处’?’是类型实参,而不是类型形参 。

可以解决当具体类型不确定的时候,这个通配符就是 ? ;当操作类型时,不需要使用类型的具体功能时,只使用Object类中的功能。那么可以用 ? 通配符来表未知类型。

例如下面的代码

    public void showKeyValue1(Generic<Number> obj){
        Log.d("泛型测试","key value is " + obj.getKey());
    }
    public void showKeyValue2(Generic<?> obj){
        Log.d("泛型测试","key value is " + obj.getKey());
    }
    Generic<Integer> gInteger = new Generic<Integer>(123);
    Generic<Number> gNumber = new Generic<Number>(456);
	//此时传入Integer将会报错
	//因为系统会判定为这是两个类型,和上面的fun2类似
	showKeyValue1(gInteger);
	//使用第二个方法时只要不使用到具体类型的方法则可以用“?”通配符
	//此时将会返回正确的答案;
	showKeyValue2(gInteger);
	

猜你喜欢

转载自blog.csdn.net/weixin_42445650/article/details/88933161
今日推荐