Java泛型学习

为什么要用泛型

Java语言引入泛型的好处是安全简单。泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率

为什么说Java泛型是假泛型,因为Java泛型只在在编译器生效(check类型检查),运行期被类型擦除,泛型还是转换成Object类型

泛型的声明

泛型类:public class Test<T>}{} T表示未知类型

泛型接口:public interface Test<T>{} 和定义类一样

泛型方法:public <T> void Test(T name){}

  • E (element) 元素 集合框架使用
  • K V (key value) 分别代表java键值中的Key Value
  • N 数字 主要用于表示数字
  • T 通用类型
  • S 通用类型
  • U 通用类型
  • V通用类型
泛型接口
/**
 * @author zzy
 * @createDate: 2022-02-08 16:31:55
 * @description: 泛型接口1
 */
public interface GenericityInterface<T> {
	//喜欢
    T like( T like);
}

/**
 * @author zzy
 * @createDate: 2022-02-08 16:31:55
 * @description: 泛型接口2
 */
public interface GenericityInterface2<T> {
	//爱好
    void  hobby (T hobby);
}
泛型类

/**
 * @author zzy
 * @createDate: 2022-02-08 16:08:12
 * @description: 泛型类
 *  实现泛型接口的时候就声明类型GenericityInterface<String>,
 *	要么创建类的时候声明类型 GenericityInterface2<S> ->  g.hobby("飞");
 */
public class GenericityClass<T, S extends String > implements GenericityInterface<String>, GenericityInterface2<S> {
    private T name;

    public GenericityClass() {
    }

    public GenericityClass(T name) {
        this.name = name;

    }

    public T getName() {
        return name;
    }

    public void setName(T name) {
        this.name = name;
    }

    //喜欢
    @Override
    public String like(String like) {
        return "我喜欢吃"+like;
    }
    //爱好
    @Override
    public void hobby(S hobby) {
        System.out.println(hobby + ":" + hobby.getClass().getName());
    }

    public static void main(String[] args) {
        //声明泛型类型
        GenericityClass<String, String> g = new GenericityClass<>("张三");
        //喜欢
        System.out.println(g.like("肉"));
        //爱好
        g.hobby("飞");
    }
}

泛型方法
/**
 * @author zzy
 * @createDate: 2022-02-08 16:35:27
 * @description: 泛型方法
 */
public class GenericityMethod {

    //1.单个泛型
    public <T> T getName1(T name) {
        return name;
    }
    //2.多个泛型
    //总的来说就是参数需要多少泛型,返回值前面就得定义几个泛型要不然编译期会出错
    public <T, K, V> void getNameAndValueAndV(T name, K value, V v) {
    }
    
    //3.使用通配符
    //3.1  <?> :无边界的通配符,能接收所有未知类型的泛型,参数必须是其它泛型类,类型不能复用,其它和方法1没区别
    public void getName2(List<?> list) {
    }
    
    //3.2 <? extends Number> :上边界通配符,元素类型必须是Number的子类
    public void getName3(List<? extends Number> name) {
    }

    //3.3 <? super Integer> :下边界通配符,元素类型必须是Integer的父类
    public void getName4(List<? super Integer> name) {
    }
    
}
泛型通配符
  • <?> :无边界的通配符,能接收所有未知类型的泛型
  • <? extends E> :上边界通配符,<? extends Number> :上边界通配符,元素类型必须是Number的子类
  • <? super E> :下边界通配符,<? super Integer> :下边界通配符,元素类型必须是Integer的父类

泛型和通配符的使用

1.总是弄不清<T>和<?>

<T>是指这里可以接受一个类型,作为模板复用,T可以当作类型来在类或者方法的上下文中复用

public class GenericityClass<T, S extends String > implements GenericityInterface<String>, GenericityInterface2<S> {
    private T name;
}

而<?>是在创建一个泛型类时不确定具体的类型,而是无限定类型

public static void main(String[] args) {
       //1.<String, String> 确定泛型类型
        GenericityClass<String, String> g = new GenericityClass<>("张三");
       //2.<?, String>  第一个T依然不确定类型,符合get原则
        GenericityClass<?, String g2 = new GenericityClass<>();
    	//可以get(),虽然类型是Object
    	Object name = g2.getName();
    	//不可以set,因为类型未知
	    //g2.setName("张三");
    
}

image-20220209152536480

小结

<T>是创建泛型模板时使用,类上接口上方法上,告诉这里需要接受一个类型,相当于方法形参

<?>是初始化对象时使用,方法形参上或方法体中,告诉这里的类型具体是什么<?>就是无限定都可以,其实和String,Integer没什么区别,相当于方法实参
2.extends和super
  • extends 上边界通配符

  • super 下边界通配符

public static void main(String[] args) {
        //3.<? extends Number, String >
        GenericityClass<? extends Number, String > g3 = new GenericityClass<>();
    	//可以get
        Number name1 = g3.getName();
        //不可以set,因为类型未知
        //g3.setName(1);
        // 4.<? super Integer, String >
        GenericityClass<? super Integer, String > g4 = new GenericityClass<>();
        //get() 类型为Object
        Object name2 = g4.getName();
        //可以set,因为类型未知
        g4.setName(1);
   
}
3.< T extends E> & < ? extends E> 和< T super E> & < ? super E>
这里其实和<T>与<?>区别不大,使用时机和使用地方都是一样的
关键是extends是上边界通配符,super 是下边界通配符,
缩小了泛型的范围;    

,因为类型未知
g4.setName(1);

}


##### 3.< T extends E> & < ? extends E> 和< T super E> & < ? super E>

这里其实和与<?>区别不大,使用时机和使用地方都是一样的
关键是extends是上边界通配符,super 是下边界通配符,
缩小了泛型的范围;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值