java泛型学习篇(二)

java泛型学习篇(二)

1 自定义泛型类

1.1 基本语法

Class 类型 <T,R,M...>{
//成员,其中...代表<>括号里面的参数可以有多个ja
}

1.2 注意点

1.2.1 属性和方法都是可以使用泛型的
 T t;
 //属性使用泛型,合法
 public T getT() {
        return t;
 }
//方法使用泛型,合法
public void setT(T t) {
    this.t = t;
}
1.2.2 使用泛型的数组不能再类中初始化
//数组在new的时候不能确定T的类型,就无法创建内存空间
R[] rs=new R[8];//错误的写法 ❌
1.2.3 静态类和静态方法都是不可以使用泛型的
//如果静态方法和静态属性使用了泛型,JVM就无法完成初始化
//因为静态是和类相关的,在类加载中,对象还没有创建
static T t1;
public static R getOne() {//返回类型可以使用泛型
    return r;
}
1.2.4 泛型类的类型是再创建的时候确定的
ArrayList<Employee> arr = new ArrayList<Employee>();
//在编译期间,就确定了该泛型的类型为Employeev
1.2.5 如果创建对象,并没有指定泛型对应的数据类型,那么默认就是Object
ArrayList arr = new ArrayList();
//这种没有指定泛型,默认就是Object类型
//public class ArrayList<E> extends AbstractList<E>

2 自定义泛型接口

2.1 基本语法

interface 接口名<T,R,M...>
//其中...代表是<>里面所写的泛型的标识符类型可以是多个

2.2 注意点

2.2.1 接口中,静态成员有不能使用泛型
T t="123";
//这样是不行,因为接口中没有写参数的方法默认是被static修饰的方法
//static决定是类加载时就创建好了.那个时候压根就没有对象耶。
2.2.2 泛型接口的类型,由继承接口和实现接口确定
interface A extends B<String,Double>
 //当我们实现A接口时,指定了T为String类型,R为double类型   
//接口B中所有的方法的泛型约束都会改成<String,Double>
2.3 在默认方法中(jdk8及其以后)也是可以使用泛型的
//实现接口时,直接指定泛型接口的类型
//其是给该类中所重写的接口中原有的泛型替换成指定的类型
//如下面的D<Integer,Double>说明了B类中重写了D接口的方法的第一个泛型参数为Intger,第二个参数为Double类型
重写的时候替换的
class C implements D<Integer,Double>
2.4 没有指定类型时.默认是Object类型
Class A implements B 写法一等价于 class A implements B<Object,Object>  写法二
//B是接口,里面使用了泛型约束符(T、R、M、E之类的)
//其中A类重写的B接口的方法都会被<Object,Object>替换掉(不会展示泛型标识符)
//虽然这样写不会报错,但是建议写成写法二

3 自定义泛型方法

3.1 基本语法

修饰符 <T,R,E...> 返回类型 方法名(参数列表){
   //与之前方法的区别是返回类型前面多了个<T,R,E...>
}

3.2 注意点

3.2.1 泛型方法可以定义在普通类中,也可以定义在泛型类中
a 普通类中
class Teacher{
    //<E,t>就是泛型,是给say方法去使用的
    public <E,T> void say(E e,T t){//泛型方法
        
    }
}
b 泛型类中
class Student<T,R>{ //泛型类
   //一般泛型方法的泛型标识符和泛型标识符不一致
   public<U,M> void eat(U u,M m){//泛型方法
       
   }  
}
3.2.2 当泛型方法被调用时,类型会确定
Teacher t=new Teacher();
t.say("小红",123);
//当调用方法时,传入参数,编译器会自动确定类型
//你传的是什么类型,那边通过getClass得到的就是什么类型
3.3.3 修饰符后没有<T,R>,那么该方法不是泛型方法,而是使用了泛型
//tell方法不是泛型方法,而是使用了泛型的方法
public void tell(T t){
}
3.3.4 泛型方法可以使用类声明的泛型,也可以使用自己声明的泛型
class Student<T,R>{ //泛型类
    //t是使用了类声明的泛型,u是使用了自己声明的泛型
   public<U> void eat(T t,U u){//泛型方法
       
   }  
}

4 泛型方法练习

4.1 题目内容

/**
 题目内容1:Apple类方法有问题吗?,若有请指出问题
 在题目内容1 基础上去运行后面的代码,会输出什么样子的结果
*/
class Apple<T,R,M>{
    public<E> void floy(E e){
         //输出当前类名(不含包名)
         System.out.println(e.getClass().getSimpleName());
    }
    public Void eat(U u){}
    public void run(M m){}
}
//题目内容2
Apple<String,Integer,Double> apple=new Apple<>();
apple.fly(10); 
apple.fly(new Dog());

4.2 题目解答

class Apple<T,R,M>{
    public<E> void floy(E e){
         //输出当前类名(不含包名)
         System.out.println(e.getClass().getSimpleName());
    }
    public Void eat(U u){} //①这句话会报错,因为并没有类没有声明该泛型标识符,且该方法也不是泛型方法
    public void run(M m){}
}
//题目内容2
//②T--->String类型,R----->Integer,M----->Double类型
Apple<String,Integer,Double> apple=new Apple<>();
apple.fly(10); //打印的是Integer类型,因为fly方法形参使用的是泛型(泛型是不支持基本数据类型的),那么数据类型会自动装箱成Interger
apple.fly(new Dog());//打印的是Dog类型

5 泛型的继承和通配符

5.1 泛型是不具备继承性的

 ArrayList<Object> arr = new ArrayList<String>();//❌

5.2 <?>支持任意泛型类型

//List<?>表示任意泛型的List集合都会被接收
public static void m1(List<?> c) {
    for (Object object : c) {
    	System.out.println(object);
    }
}

5.3 <? extends A> 支持A类以及A类的子类,规定了泛型的上限

//List<? extends AA>表示上限,AA和AA子类都可以接收
public static void m2(List<? extends AA> c) {
    for (Object object : c) {
    	System.out.println(object);
    }
}

5.4 <? super A> 支持A类以及A类的父类,不限于直接父类,规定了泛型的下限

/List<? super AA>表示下限为AA,AAAA的所有父类都可以接受,不限于直接父类
public static void printCollection2(List<? super AA> c) {
    for (Object object : c) {
    	System.out.println(object);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SSS4362

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值