泛型总结(代码片段)

linzhanfly linzhanfly     2023-01-06     457

关键词:

一 容器类:请取出同一类型的物品

1 不使用泛型

// A是B的父类
List list = new ArrayList<>();
list.add(new A());
list.add(new A());
list.add(new String());

System.out.println((A)list.get(0));
System.out.println((A)list.get(1));
// 编译时不报错,运行时报错:java.lang.ClassCastException
System.out.println((A)list.get(2)); 

2 不恰当泛型

// A是B的父类
List<A> list = new ArrayList<>();
list.add(new A());
list.add(new B());
// list.add(new String()); // 加上时,编译会报错

System.out.println((B)list.get(0));
// 编译时不报错,运行时报错:java.lang.ClassCastException
System.out.println((B)list.get(1)); 
  • 补救方案:先进行类型判断
A a1 = list.get(1);
if(a1.getClass() == B.class)
    System.out.println((B)a1); 

3 正确使用泛型

// A是B的父类
List<A> list = new ArrayList<>();
list.add(new A());
list.add(new B());

// 如果把B放入A的容器中,就把B当成A使用,不要想着强转回来使用了。
System.out.println(list.get(0));
System.out.println(list.get(1));

4 总结

  • 没有泛型时,不能依赖编译器的语法检查,由于List 等同于 List<Object>。
  • 泛型能够给编译器提供类型检查。
  • 父类容器虽然可以放入子类,但取出来尽量不要还原回子类进行使用,费时费力。

二 泛型通配符

1 准备

public class Main 
    static class A 

    

    static class B extends A 

    

    static class C<T>
        private T t;

        public C()

        

        public T getT() 
            return t;
        

        public void setT(T t) 
            this.t = t;
        
    

2 测试

(1)类型擦除和类型强转

  • java
public class Main 
    public static void main(String[] args) 
        C<A> cA = new C<>();
        // 类型强转:这就是为什么1.1节中编译不报错,运行时报错的原因。编译时类型擦错,并不进行检查。
        // Object obj = cA.getT();
        // A t = (A)obj;
        A t = cA.getT(); 
    
  • 字节码
public static void main(java.lang.String[]);
    Code:
       0: new           #2       // class Main$C
       3: dup
       4: invokespecial #3       // Method Main$C."<init>":()V
       7: astore_1
       8: aload_1
       9: invokevirtual #4       // Method Main$C.getT:()Ljava/lang/Object;
      12: checkcast     #5       // class Main$A
      15: astore_2
      16: return

(2)C<A>和C<B>是相同类型吗?

public static void main(String[] args) 
    C<A> cA = new C<>();
    C<B> cB = new C<>();
    // 为什么Class<? extends C> 而不是Class<C> Class<?> Class<? super C> ?
    Class<? extends C> aClass = cA.getClass();
    Class<? extends C> bClass = cB.getClass();
    boolean b = aClass == bClass; // true

(3)通配符作为入参

  • demo1
public static void main(String[] args) 
    C<A> cA = new C<>();
    C<B> cB = new C<>();
    test(cA);
    test(cB); // 编译时错误:Error: java: 不兼容的类型


public static void test(C<A> c)
    A a = c.getT();
  • demo2: C<Object>不是C<A>的父类
public static void main(String[] args) 
    C<A> cA = new C<>(new A());
    C<B> cB = new C<>(new B());
    test(cA); // 编译时错误:Error: java: 不兼容的类型
    test(cB); // 编译时错误:Error: java: 不兼容的类型


public static void test(C<Object> c) 
    Object t = c.getT();
  • demo3:C<?>接收所有类型
public static void main(String[] args) 
    C<A> cA = new C<>(new A());
    C<B> cB = new C<>(new B());
    test(cA);
    test(cB);


public static void test(C<?> c)  // 或者C c也行
    Object t = c.getT();
  • demo4:定义上界限,泛型是A或者继承A即可。
public static void main(String[] args) 
    C<A> cA = new C<>(new A());
    C<B> cB = new C<>(new B());
    test(cA);
    test(cB);


public static void test(C<? extends A> c) 
    A t = c.getT();
  • demo5:定义下界限,泛型是A或A的父类。
public static void main(String[] args) 
    C<A> cA = new C<>(new A());
    C<B> cB = new C<>(new B());
    test(cA);
    test(new C<Object>());
    test(cB); // 编译时报错:


public static void test(C<? super A> c) 
    Object t = c.getT();

(4)统配符作为返回值

  • demo1:可以修改,但是需要是泛型是A或者A的子类.
public static void main(String[] args) 
    C<A> test = test();
    test.setT(new A());
    test.setT(new B());
    test.setT(new Object()); // 编译错误


public static C<A> test() 
    C<A> cA = new C<>(new A());
    return cA;
  • demo2:?返回,无法修改,只能读取
public static void main(String[] args) 
    C<?> test = test();
    test.setT(new A()); // 编译错误
    test.setT(new B()); // 编译错误
    test.setT(new Object()); // 编译错误


public static C<?> test() 
    C<A> cA = new C<>(new A());
    return cA;
  • demo3:?extends 返回,无法修改,只能读取,和demo2相同,但是类中的泛型是什么。
public static void main(String[] args) 
    C<? extends A> test = test();
    test.setT(new A()); // 编译错误
    test.setT(new B()); // 编译错误
    test.setT(new Object()); // 编译错误


public static C<? extends A> test() 
    C<A> cA = new C<>(new A());
    return cA;
  • demo4:可以修改,但泛型需要是A或者继承A的类,和demo1相同。
public static void main(String[] args) 
    C<? super A> test = test();
    test.setT(new A());
    test.setT(new B());
    test.setT(new Object()); // 编译错误


public static C<? super A> test() 
    C<A> cA = new C<>(new A());
    return cA;
  • 结论:
    • 泛型返回时,如果可以修改则指定泛型类型即可,如demo1
    • 泛型返回时,如果不可以修改,则使用demo3,这样可以知道泛型类型是什么。这也是为什么c.getClass()方法返回Class<? extends C>的原因。

(5)泛型多继承

static class A 

static interface D 

// extends 类或接口 & 接口 & 接口 ...
static class C<T extends A & D & Comparable> 
    private T t;

3 总结

  • 编译时进行类型擦除,取出时进行类型强转。
  • Class类型相同,但是泛型类型不同。
  • 传参:Class类型相同情况下
    • ?:接收所有类型的泛型类型
    • ? extends T:接收泛型类型为T或者T的子类
    • ? super T:接收泛型类型为T或者T的父类
    • T:只接收泛型类型为T
  • 返回:都支持读取
    • ?:无法修改
    • ? extends T:无法修改,但知道泛型类型为T
    • ?super T:支持修改为T或T的子类的对象
    • T:支持修改为T或T的子类的对象
  • 泛型继承:T extends 类或者接口 & 接口 & 接口 ...

java泛型相关总结(上)(代码片段)

最近在看《Java核心技术》泛型相关的部分,总结下。泛型程序设计是什么?泛型编程(genericprogramming)是计算机编程中的一种风格,类型通过参数指定。意味着编写的代码可以被不同类型的对象所使用。类型参数(typeparameters)... 查看详情

泛型总结(代码片段)

一容器类:请取出同一类型的物品1不使用泛型//A是B的父类Listlist=newArrayList<>();list.add(newA());list.add(newA());list.add(newString());System.out.println((A)list.get(0));System.out.println((A)list.get(1));//编译时不报错,运行时报 查看详情

java泛型常问面试题总结(代码片段)

文章目录Java泛型常问问题1.Java中的泛型是什么?使用泛型的好处是什么?2.如何编写一个泛型方法,让它能接受泛型参数并返回泛型类型?3.下面能编译通过?4.Array中可以用泛型吗?5.编写Employee类6.你可以把`List`传递给... 查看详情

java泛型常问面试题总结(代码片段)

文章目录Java泛型常问问题1.Java中的泛型是什么?使用泛型的好处是什么?2.如何编写一个泛型方法,让它能接受泛型参数并返回泛型类型?3.下面能编译通过?4.Array中可以用泛型吗?5.编写Employee类6.你可以把`List`传递给... 查看详情

java基础知识点笔记总结(代码片段)

文章目录1.泛型定义2.泛型的小细节3.泛型自定义泛型4.泛型自定义泛型注意点5.泛型方法6.泛型继承注意点7.泛型通配符?8.泛型有限制条件的通配符?9.File类9.1File类的使用9.2file类的常用方法9.3file类总结10.IO流11.IO流体系对... 查看详情

java基础总结三(泛型异常)(代码片段)

文章目录Java基础总结三(泛型、异常)泛型泛型的创建泛型类泛型接口泛型方法类型擦除泛型的协变与逆变异常异常体系异常处理Java基础总结三(泛型、异常)泛型泛型的创建泛型类我们最常用泛型的地方就是... 查看详情

java泛型知识总结篇(代码片段)

泛型与内部类非静态内部类会自动继承外围类泛型参数,对于非静态内部类,无需再次声明泛型参数静态内部类不会自动继承外围类泛型参数(事实上,Node中的泛型参数与MyLinkedList中的没有任何联系,只是这里使用相同的符号T而... 查看详情

java:泛型类型使用总结(代码片段)

    泛型是Sun公司发布的JDK5.0中的一个重要特性,它的最大优点是提供了程序的类型安全同可以向后兼容。为了帮助读者更好地理解和使用型,本文通过一些示例从基本原理,重要概念,关键技术,以及相似... 查看详情

201771010123汪慧和《面向对象程序设计java》第十周实验总结(代码片段)

一、理论部分1、泛型:也称参数化类型。就是定义类、接口和方法时,通过类型参数指示将要处理的对象类型。2、泛型程序设计:编写代码可以被很多不同类型的对象所重用。3、泛型方法:a.除了泛型类外,还可以只单独定义... 查看详情

kotlin语法总结-泛型的使用(代码片段)

怎样声明一个函数来判断两个参数是否相等呢?如果参数是Int类型,则函数声明如下:privatefunisEqualsInt(a:Int,b:Int):Boolean     return(a==b)这个函数参数列表是两个Int类型,它只能比较两个Int类型参数是否相等... 查看详情

java泛型总结(代码片段)

泛型总结Java泛型Java泛型(generics)是JDK5中引入的一个新特性,泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。泛型... 查看详情

201771010135杨蓉庆《面对对象程序设计(java)》第十周学习总结(代码片段)

1、实验目的与要求(1) 理解泛型概念;(2) 掌握泛型类的定义与使用;(3) 掌握泛型方法的声明与使用;(4) 掌握泛型接口的定义与实现;(5)了解泛型程序设计,理解其用途。一、理论知识泛型类的定义:(1)泛型:... 查看详情

李瑞红201771010111第十周学习总结(代码片段)

---恢复内容开始---实验十 泛型程序设计技术实验时间2018-11-1第一部分:理论知识总结1.泛型也称为参数化类型,就是在定义类、方法、接口时,通过类型参数指示将要处理的对象类型。.2.泛型程序设计:编写代码可以被很多... 查看详情

201771010108-韩腊梅-第十周学习总结(代码片段)

第十周总结一、知识总结1.定义简单泛型类  1.1一个泛型类Genericclass就是具有一个或多个类型变量的类  1.2Java中,使用E表示集合的元素类型,K和V表示Map的关键字和值的类型。T(需要时还可以使用临近的U和S)表示... 查看详情

java——泛型(代码片段)

文章目录Java中泛型的概述Java中泛型的语法规则泛型集合泛型方法泛型方法示例(代码演示)小结泛型类泛型类示例(代码演示)小结泛型接口泛型接口示例(代码演示)高级泛型总结Java中泛型的概述泛型... 查看详情

java编程思想--泛型概括总结(代码片段)

在面向对象编程语言中,多态算是一种泛化机制。例如你可以将方法的参数类型设为基类,那么该方法就可以接受从这个类中导出的任何类作为参数。但是,考虑到除了final类不能扩展,这种灵活性大大降低。如... 查看详情

201771010128王玉兰《面向对象程序设计(java)》第十周学习总结(代码片段)

第一部分:理论知识部分总结:(1)定义简单泛型类:A:泛型:也称参数化类型(parameterizedtype),就是在定义类、接口和方法时,通过类型参数指示将要处理的对象类型。B:泛型程序设计(Genericprogramming):编写代码可以被很多不... 查看详情

杨玲201771010133《面向对象程序设计(java)》第十周学习总结(代码片段)

...结第一部分:理论知识学习部分  第八章  泛型程序设计一、泛型程序设计的定义1、JDK5.0中增加的泛型类型,是Java语言中类型安全的一次重要改进。2、泛型:也称参数化类型(parameterizedtype),就是在定义类、接口... 查看详情