Java泛型的小结

什么是泛型?
  • 泛型:把类型明确的工作推迟到创建对象或调用方法的时候才去明确的特殊的类型,JDK5之后引入。
  • 参数化类型:把类型当作参数传递,<数据类型>只能是引用类型
泛型的作用
  • 可以让多种数据类型使用同一份代码
  • 编写时指定类型,插入错误的数据类型会报错,只要编译时没报错,运行时就不会出现ClassCastException异常,使用时不需要强转
泛型类,接口,方法
  • 泛型类
    public class Generic<T> {
    	public T data;
     }
    
  • 泛型接口以及它的两种实现
    public interface IGeneric<T> {
        T get(T a);
    }
    
    class BGeneric<T> implements IGeneric<T> {//子类不明确泛型类的类型参数变量
        @Override
        public T get(T a) {
            return null;
        }
    }
    
    public class AGeneric implements IGeneric<String> {//子类明确了泛型类的类型参数变量
        @Override
        public String get(String a) {
            return null;
        }
    }
    
  • 泛型方法(在访问修饰符和返回值类型有一个<数据类型>, 如<T>)
    public <T> void printTest(T t){
        System.out.println(t.getClass().getName());
    }
    
  • 泛型类定义的数据类型只对它内部的普通方法有效,泛型方法的数据类型由它自身定义决定
    public class GenericClass<T> {
        public T data;
    
        public void print(T t){
            System.out.println(t.toString());
        }
    
        public <E> String getClassName(E e){
            return e.getClass().getName();
        }
    
        public static void main(String[] args) {
            GenericClass<String> genericClass = new GenericClass<>();
            genericClass.print("泛型类定义的数据类型");
    
            String className = genericClass.getClassName(new ArrayList<>());
            System.out.println(className);
        }
    }
    
    输出结果:
    泛型类定义的数据类型
    java.util.ArrayList
    
泛型限定符(extends)
`<T>` 类型变量只能extends一个类,可以实现多个接口(使用&),类必须放在第一个
  • 类型变量的限定-方法上
    public class ArrayAlg {
        public static <T extends ArrayList&Comparable> T min(T a, T b){
            if (a.compareTo(b) > 0)
                return a;
            else
                return b;
        }
        
    	//没有继承ArrayList,实现Comparable,min方法会报错
        static class Test{}
        
        //正常的
    	static class Test extends ArrayList implements Comparable{
            @Override
            public int compareTo(Object o) {
                return 0;
            }
        }
    
        public static void main(String[] args) {
            min(new Test(), new Test());
        }
    }
    
  • 类型变量的限定-类上
    public class ClassBorder<T extends Comparable> {
        private T data;
        
        public T min(T outter){
            if (this.data.compareTo(outter) > 0)
                return outter;
            else 
                return this.data;
        }
    
        public T getData() {
            return data;
        }
    
        public void setData(T data) {
            this.data = data;
        }
    
        public static void main(String[] args) {
            ClassBorder<String> classBorder = new ClassBorder<>();
            classBorder.setData("tina");
            System.out.println(classBorder.min("jim"));
        }
    }
    
泛型的局限性
  • 不能实例化类型变量
  • 不能在静态域或方法中使用类型变量,除非静态方法本身是泛型方法,因为构造方法晚于静态域或方法执行,而泛型在实例化的时候才知道具体的类型
  • 泛型定义的数据类型只能是引用类型,不能是基本类型
  • 泛型类不能继承Exception/Throwable,不能捕获泛型类对象,但是可以抛出泛型
    public class ExceptionRestrict {
        /*泛型类不能extends Exception/Throwable*/
    	//private class Problem<T> extends Exception;
    
        /*不能捕获泛型类对象*/
    //    public <T extends Throwable> void doWork(T x){
    //        try {
    //
    //        }catch (T e){
    //
    //        }
    //    }
    
        public <T extends Throwable> void doWorkSucceed(T x) throws T {
            try {
    
            }catch (Throwable e){
                throw x;
            }
        }
    }
    
  • 运行时类型查询使用下面的方法是错误的,因为类型擦除后,Generic<String>只剩下原始类型Generic
    Generic<String> generic = new Generic();
    if(generic instanceOf Generic<String>){
    }
    
    java限定了下面这种类型方式查询,?是通配符
    if(generic instanceOf Generic<?>){
    }
    
  • 不能创建参数类型的数组;
    GenericType<String>[] types = new GenericType<String>[10];//报错
    
泛型的继承规则
  • Apple extend Fruits,但Generic<Apple>Generic<Fruits>没有任何关系
  • ExtendGeneric<T> extends Generic<T>这种继承是可以的
    class Fruits {}
    class Apple extend Fruits {
    }
    public class Generic<T> {
        public void printName(Generic<Fruits> t){
            System.out.println(t.toString());
        }
        public static void main(String[] args) {
            Generic<Fruits> generic1 = new Generic<>();
            //情况1
            //Generic<Apple> generic2 = new Generic<>();
            //generic1.printName(generic2);会报错
            
            //情况2
    		ExtendGeneric<Fruits> generic2 = new ExtendGeneric<>();
            generic1.printName(generic2);
        }
    
    	static class ExtendGeneric<T> extends Generic<T> {
    
        }
    }
    
    
泛型通配符(?)
  • 通配符上限
    <?extends Type>传递进来的只能是Type或Type的子类
    该类型的实例,能安全的调用get方法,返回值只能用Type接收,不能调用set方法

  • 通配符下限
    <?super Type>传递进来的只能是Type或Type的父类
    该类型的实例,set方法可以传Type的本身或子类,get返回值只能用Object接收

    代码如下:(class关系:HongFuShi -> Apple -> Fruit ->Food ; Orange -> Fruit-> Food;)

    public class GenericType<T> {
        private T data;
    
        public T getData() {
            return data;
        }
    
        public void setData(T data) {
            this.data = data;
        }
    }
    
    public class WildChar {
    	//不使用通配符的情况
        public static void print(GenericType<Fruit> p) {
            System.out.println(p.getData().getColor());
        }
    	//不使用通配符的情况,只能传入定义的类型
        public static void use() {
            GenericType<Fruit> a = new GenericType<>();
            print(a);
            GenericType<Orange> b = new GenericType<>();
    //        print(b);
        }
    
    	//使用上限通配符
        public static void print2(GenericType<? extends Fruit> p) {
            System.out.println(p.getData().getColor());
        }
    
        public static void use2() {
            GenericType<Fruit> a = new GenericType<>();
            print2(a);
            GenericType<Orange> b = new GenericType<>();
            print2(b);
    //        print(new GenericType<Food>());
            GenericType<? extends Fruit> c = new GenericType<>();
            Apple apple = new Apple();
            Fruit fruit = new Fruit();
    //        c.setData(apple);
    //        c.setData(fruit);
            Fruit x = c.getData();
        }
    
    	//使用下限通配符
        public static void printSuper(GenericType<? super Apple> p) {
            System.out.println(p.getData());
        }
    
        public static void useSuper() {
            GenericType<Fruit> fruitGenericType = new GenericType<>();
            GenericType<Apple> appleGenericType = new GenericType<>();
            GenericType<HongFuShi> hongFuShiGenericType = new GenericType<>();
            GenericType<Orange> orangeGenericType = new GenericType<>();
            printSuper(fruitGenericType);
            printSuper(appleGenericType);
    //        printSuper(hongFuShiGenericType);
    //        printSuper(orangeGenericType);
    
            //表示GenericType的参数类型的下界是Apple
            GenericType<? super Apple> x = new GenericType<>();
            //set能传入Type的本身以及子类型
            x.setData(new Apple());
            x.setData(new HongFuShi());
    //        x.setData(new Fruit());
            Object o = x.getData();//get只能用Object接收,Apple的顶级父类Object
        }
    }
    
JVM中如何处理泛型
  • 泛型擦除(为了兼容JDK5以前的版本)
    泛型是提供给javac编译器使用的,它用于限定集合的输入类型,让编译器在源代码级别上,即挡住向集合中插入非法数据。但编译器编译完带有泛形的java程序后,生成的class文件中将不再带有泛型信息,以此使程序运行效率不受到影响,这个过程称之为“擦除”。类型变量被擦除(crased),并使用其限定类型(无限定的变量用Object)替换。
  • 泛型擦除带来的一个小冲突,如下定义的两个方法会报错,因为擦除后类型一样,不是重载;
    public class Conflict {
        public static void method(List<String> list){
    
        }
        public static void method(List<Integer> list){
    
        }
    }
    
    编译报错
    泛型擦除可以看看这篇文章:
    java泛型(二)、泛型的内部原理:类型擦除以及类型擦除带来的问题
本项目是一个基于SSM(Spring+SpringMVC+MyBatis)框架和Vue.js前端技术的家教平台系统。该系统旨在为家教和学生提供一个便捷、高效的在线交流和预约平台,涵盖了从用户注册登录、个人信息管理、课程发布与搜索、预约与取消预约、评价反馈等一系列功能。 在后台管理方面,系统提供了管理员对用户信息、课程信息、预约记录等进行管理的功能,确保平台的正常运行和数据的准确性。通过Spring框架的依赖注入和AOP特性,实现了业务逻辑的清晰分离和高效处理;SpringMVC则负责处理前端请求和响应,提供友好的用户界面;MyBatis作为ORM框架,简化了数据库操作,提高了数据访问的效率和安全性。 前端部分采用Vue.js框架,结合Vue Router进行页面路由管理,Axios进行HTTP请求,实现了前后端分离的开发模式。Vue.js的组件化开发和响应式数据绑定特性,使得前端页面更加动态和交互性强,提升了用户体验。 数据库设计采用了MySQL,存储了用户信息、课程信息、预约记录等核心数据。通过合理的数据库表结构和索引设计,保证了系统的高效运行和数据的一致性。 该项目不仅适合计算机相关专业的毕设学生参考和学习,也适合Java学习者进行项目实战练习。通过对该项目的深入理解和二次开发,可以实现更多个性化功能,进一步提升技术水平和实践能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值