Java 泛型

1 泛型

所谓泛型就是标签,例如中药店的标签 就是允许在定义类、 接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。 这个类型参数将在使用时(例如,继承或实现这个接口, 用这个类型声明变量、 创建对象时) 确定(即传入实际的类型参数, 也称为类型实参)

  • 从JDK1.5以后, Java引入了“ 参数化类型( Parameterized type)” 的概念,允许我们在创建集合时再指定集合元素的类型, 正如: List, 这表明该List只能保存字符串类型的对象。
  • JDK1.5改写了集合框架中的全部接口和类, 为这些接口、 类增加了泛型支持,从而可以在声明集合变量、 创建集合对象时传入类型实参。
  • 集合没有泛型时:读取出数据需要强制类型转换,有可能抛出ClassCastExceptio
    在这里插入图片描述
  • 集合中使用泛型:可以避免强转,避免抛出ClassCastException
    在这里插入图片描述
    List使用泛型案例
public class ListTest {

    /**
     * 没有泛型
     */
    @Test
    public void test1() {
        List list = new ArrayList();

        list.add(123);//存入 int 装箱 Integer

        String str = (String) list.get(0);//ClassCastException
    }

    /**
     * 使用泛型
     */
    @Test
    public void test2() {
//        List <String> list = new ArrayList<String>();//jdk1.5
        List<String> list = new ArrayList<>();

        list.add("123");//因为泛型,只能存String

        String str = list.get(0);//泛型的主要作用:避免强制类型转换
    }

    /**
     * 泛型list循环
     */
    @Test
    public void test3(){
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);

        //迭代器循环
        Iterator<Integer> it = list.iterator();
        while (it.hasNext()){
            Integer i = it.next();
            System.out.println(i);
        }

        //增强for循环
        for (Integer i : list) {
            System.out.println(i);
        }

    }

}

Map使用泛型案例

public class MapTest {

    @Test
    public void test1() {
        Map map = new HashMap();

        map.put("a", 111);
        map.put(222, "b");
        map.put(new Date(), "ccc");

        Set set = map.entrySet();
        //EntrySet
        for (Object obj : set) {
            Map.Entry entry = (Map.Entry) obj;
            System.out.println(entry.getKey() + " " + entry.getValue());
        }

        System.out.println("=================");
        //keySet
        Set keys = map.keySet();
        for (Object obj : keys) {
            System.out.println(obj + " " +map.get(obj));
        }
    }

    @Test
    public void test2(){
    //        Map<String, Integer> map = new HashMap<String, Integer>();
        Map<String,Integer> map = new HashMap<>();

        map.put("a",1);
        map.put("a",1);
        map.put("b",1);
        map.put("c",1);
        map.put("d",1);
        map.put("e",1);
        map.put("f",1);
        map.put("g",1);
        map.put("h",1);



        //EntrySet
        for (Map.Entry<String,Integer> entry : map.entrySet()){
            System.out.println(entry.getKey() + " " + entry.getValue());
        }

        System.out.println("=================");

        //keySet
        Iterator<String> it = map.keySet().iterator();
        while (it.hasNext()){
            String key = it.next();
            System.out.println("key = " + key + "value =" + map.get(key));
        }
    }
}

2 自定义泛型

2.1 泛型类

  • 在类声明时使用泛型约束这个类使用的泛型类型

语法

//格式
public class 类名 <泛型类型1,...> {
    
}

案例

public class GenericsCls<T1, T2> {

    public void f1(T1 arg1, T2 arg2){

        System.out.println(arg1);
        System.out.println(arg2);
    }

    private T1 t1;

    private T2 t2;

    public T1 getT1() {
        return t1;
    }

    public void setT1(T1 t1) {
        this.t1 = t1;
    }

    public T2 getT2() {
        return t2;
    }

    public void setT2(T2 t2) {
        this.t2 = t2;
    }
}

测试

public class Test1 {

    public static void main(String[] args) {
        GenericsCls<String, Date> bean = new GenericsCls<>();
        bean.f1("abc", new Date());

        bean.setT1("t1 = 1");
        bean.setT2(new Date());

        System.out.println(bean.getT1());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        System.out.println(sdf.format(bean.getT2()));

        GenericsCls<String, Clz> bean2 = new GenericsCls<>();
        bean2.f1("aaaa", new Clz());
    }
}

class Clz {
    @Override
    public String toString() {
        return "Clz{}";
    }
}

2.2 泛型方法

语法

public class GenericsMethod {

    /**
     * 泛型方法
     * @param bean
     * @param arg
     * @return
     * @param <T1>
     * @param <T2>
     */

    public static <T1, T2> T1 f1(T1 bean, T2 arg) {
        System.out.println(arg);
        return bean;
    }

    public static void main(String[] args) {
        String str = f1("abc", new Date());

        Date date = f1(new Date(), "cba");

        Integer i = f1(123,"aaa");
    }
}

2.3 泛型接口

例如

public interface GenricsInterface<T>{
    
}

//实现类
public class Clazz implements GenricsInterface<String> {
    
}

案例

public interface GenericsInterface <T>{

    public T getValue();
}
public class IntegerImpl implements GenericsInterface<Integer> {
    @Override
    public Integer getValue() {
        return 123456;
    }
}

public class StringImpl implements GenericsInterface<String>{
    @Override
    public String getValue() {
        return "hello generics interface";
    }
}

测试

public class Test1 {

    public static void main(String[] args) {
        GenericsInterface<String> g1 = new StringImpl();
        System.out.println(g1.getValue());

        GenericsInterface<Integer> g2 = new IntegerImpl();
        System.out.println(g2.getValue());
    }
}

3 泛型通配符

3.1 通配符的上边界

<? extends T>,在类型参数中使用 extends 表示这个泛型中的参数必须是 T 或者 T 的子类

案例

public class Test1 {

	public static void f1(List<? extends Father> list) {
	    }
	
	public static void main(String[] args) {
	        List<GrandFather> grandFatherList = new ArrayList<>();
	        List<Father> fatherList = new ArrayList<>();
	        List<Monther> montherList = new ArrayList<>();
	        List<Son> sonList = new ArrayList<>();
	        List<Daughter> daughterList = new ArrayList<>();
	
	        f1(sonList);
	        f1(daughterList);
	        f1(fatherList);
	//        f1(grandFatherList);// ? extend Father:表示对象边界是Father和Father的子类
	//        f1(montherList);
	
	        f2(sonList);
	        f2(daughterList);
	        f2(fatherList);
	        f2(grandFatherList);
	        f2(montherList);
	        f2(new ArrayList<String>());
	    }
	
	
	
	    class GrandFather {
	
	    }
	
	    class Father extends GrandFather {
	
	    }
	
	    class Monther {
	        Father father;
	
	    }
	
	    class Daughter extends Father {
	
	    }
	
	    class Son extends Father {
	
	    }
 }

3.2 通配符的下边界

  • ? super Father:Father和father的父类

案例

public class Test2 {


    public static void f1(List<? super Father> list) {

    }

    public static void main(String[] args) {
        List<GrandFather> grandFatherList = new ArrayList<>();
        List<Father> fatherList = new ArrayList<>();
        List<Monther> montherList = new ArrayList<>();
        List<Son> sonList = new ArrayList<>();
        List<Daughter> daughterList = new ArrayList<>();

//        f1(sonList);
//        f1(daughterList);
        f1(fatherList);
        f1(grandFatherList);// ? super Father:表示对象边界是Father和Father的父类
//        f1(montherList);
    }


    class GrandFather {

    }

    class Father extends GrandFather {

    }

    class Monther {
        Father father;

    }

    class Daughter extends Father {

    }

    class Son extends Father {

    }
}

3.3 泛型边界在接口中的应用

  • 声明接口的泛型只能使用T extends Type

案例

public class Test2 {

    class Impl1 implements GenericsInterface<Father>{
        @Override
        public Father getValue() {
            return null;
        }
    }

//    class Impl2 implements GenericsInterface<Monther>{
//        @Override
//        public Monther getValue() {
//            return null;
//        }
//    }
//
//    class Impl3 implements GenericsInterface<String>{
//        @Override
//        public String getValue() {
//            return null;
//        }
//    }
//
//    class Impl4 implements GenericsInterface<GrandFather>{
//        @Override
//        public GrandFather getValue() {
//            return null;
//        }
//    }

    class Impl5 implements GenericsInterface<Son>{
        @Override
        public Son getValue() {
            return null;
        }
    }

    class Impl6 implements GenericsInterface<Daughter>{
        @Override
        public Daughter getValue() {
            return null;
        }
    }


    interface GenericsInterface<T>{
        public T getValue();
    }

    class GrandFather {

    }

    class Father extends GrandFather {

    }

    class Monther {
        Father father;

    }

    class Daughter extends Father {

    }

    class Son extends Father {

    }

}

3.4 无界通配符

  • ?表示传入任意类型

案例

public static void f2(List<?> list){
 }
 
 public void test1(){
        f2(sonList);
        f2(daughterList);
        f2(fatherList);
        f2(grandFatherList);
        f2(montherList);
        f2(new ArrayList<String>());
    }

4 Java的泛型擦除

  • Java的泛型是伪泛型,为什么说Java的泛型是伪泛型呢?因为在编译期间,所有的泛型信息都会被擦除掉,我们常称为泛型擦除。

案例

 @Test
    public void test1(){
        List<String> stringList = new ArrayList<String>();//ArrayList<String>.class
        stringList.add("泛型");
        List<Integer> integerList = new ArrayList<Integer>();//ArrayList.class
        integerList.add(1);
        System.out.println(stringList.getClass());
        System.out.println(stringList.getClass() == integerList.getClass());//ture
    }

结果如下
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值