自定义泛型
  TEZNKK3IfmPf 2023年11月13日 19 0

class 类名  {/ /...表示可可以有多个泛型

成员

}

➢注意细节

1)普通成员可以使用泛型(属性、方法)

2)使用泛型的数组,不能初始化

3)静态方法中不能使用类的泛型

4)泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定确定类型)

5)如果在创建对象时,没有指定类型,默认为Object

代码在com.stulzl.generic_custom.包中

Generic_Custom 

package com.stulzl.generic_custom;

//自定义泛型案例说明  560
public class Generic_Custom {
    public static void main(String[] args) {

    }
}
//解读
//1. Tiger 后面泛型,所以我们把 Tiger 就称为自定义泛型类
//2, T, R, M 泛型的标识符, 一般是单个大写字母
//3. 泛型标识符可以有多个.
class Tiger{
    String name;
    //4. 普通成员可以使用泛型 (属性、方法)
    R r;
    M m;
    T t;
    //使用泛型的数组,不能初始化,但可以定义
    //因为数组在 new 不能确定 T 的类型,就无法在内存开空间
    //T[] ts = new T[8];//这里的8就是初始化
    T[] ts;

    public Tiger(String name, R r, M m, T t) {//构造器就可以使用泛型
        this.name = name;
        this.r = r;
        this.m = m;
        this.t = t;
    }

    //随便写一个静态方法
    //静态方法中不能使用类的泛型
    //因为静态是和类相关的,在类加载时,对象还没有创建
    //所以,如果静态方法和静态属性使用了泛型,JVM 就无法完成初始化
//    public static void m1(M m){
//
//    }

    public String getName() {//返回类型使用泛型
        return name;
    }

    public void setName(String name) {//方法使用泛型
        this.name = name;
    }

    public R getR() {
        return r;
    }

    public void setR(R r) {
        this.r = r;
    }

    public M getM() {
        return m;
    }

    public void setM(M m) {
        this.m = m;
    }

    public T getT() {
        return t;
    }

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

2. 应用练习  560

2.1 判断是否正确

自定义泛型

代码在com.stulzl.generic_custom_exercise01.包中

Generic_CustomExercise01
package com.stulzl.generic_custom_exercise01;

import java.util.Arrays;

//自定义泛型类练习01 判断是否正确 560
public class Generic_CustomExercise01 {
    public static void main(String[] args) {

        //T=Double  R=String  M=Integer
        Tiger g = new Tiger<>("john");
        g.setT(10.9); //OK
        //g.setT("yy"); //错误,类型不对,因为给他的泛型是Double类型
        System.out.println(g);
        Tiger g2 = new Tiger("john~~");//OK T=Object R=Object M=Object
        g2.setT("yy"); //OK ,因为 T=Object "yy"=String 是Object子类
        System.out.println("g2=" + g2);
    }
}
//解读
//1. Tiger 后面泛型,所以我们把 Tiger 就称为自定义泛型类
//2, T, R, M 泛型的标识符, 一般是单个大写字母
//3. 泛型标识符可以有多个.
class Tiger{
    String name;
    //4. 普通成员可以使用泛型 (属性、方法)
    R r;
    M m;
    T t;
    //使用泛型的数组,不能初始化,但可以定义
    //因为数组在 new 不能确定 T 的类型,就无法在内存开空间
    //T[] ts = new T[8];//这里的8就是初始化
    T[] ts;

    public Tiger(String name){
        this.name=name;
    }
    public Tiger( R r, M m, T t) {//构造器就可以使用泛型

        this.r = r;
        this.m = m;
        this.t = t;
    }

    //随便写一个静态方法
    //静态方法中不能使用类的泛型
    //因为静态是和类相关的,在类加载时,对象还没有创建
    //所以,如果静态方法和静态属性使用了泛型,JVM 就无法完成初始化
//    public static void m1(M m){
//
//    }

    public String getName() {//返回类型使用泛型
        return name;
    }

    public void setName(String name) {//方法使用泛型
        this.name = name;
    }

    public R getR() {
        return r;
    }

    public void setR(R r) {
        this.r = r;
    }

    public M getM() {
        return m;
    }

    public void setM(M m) {
        this.m = m;
    }

    public T getT() {
        return t;
    }

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

    @Override
    public String toString() {
        return "Tiger{" +
                "name='" + name + '\'' +
                ", r=" + r +
                ", m=" + m +
                ", t=" + t +
                ", ts=" + Arrays.toString(ts) +
                '}';
    }
}

3. 自定义泛型接口  561

3.1 基本语法

interface 接口名 . {

}

3.2 注意细节

1)接口中, 静态成员也不能使用泛型(这个和泛型类规定一样)

2)泛型接口的类型,在继承接口或者实现接口时确定

3)没有指定类型,默认为Object 

3.3 案例演示  561

代码在com.stulzl.generic_custom_interface.包中

Generic_customInterface

package com.stulzl.generic_custom_interface;

//自定义泛型接口  561
public class Generic_customInterface {
    public static void main(String[] args) {

    }
}
interface IUsb {
    int n = 10;
    //1)接口中, 静态成员也不能使用泛型(这个和泛型类规定一样)
    //U name; 不能这样使用,因为接口中的成员都是静态性质的

    //普通方法中,可以使用接口泛型
    R get(U u);//因为在接口中方法可以省略写

    void hi(R r);

    void run(R r1, R r2, U u1, U u2);

    //在jdk8 中,可以在接口中,使用默认方法, 也是可以使用泛型
    default R method(U u) {
        return null;
    }
}
//2) 2.1 泛型接口的类型,在继承接口或者实现接口时确定
//在继承接口 指定泛型接口的类型
interface IA extends IUsb{//IA阶乘接口IUsb,并指定泛型类型

}
//当我们去实现 IA 接口时,因为 IA 在继承 IUsu 接口时,指定了 U 为 String R 为 Double
//,在实现 IUsu 接口的方法时,使用 String 替换 U, 是 Double 替换 R
class AA implements IA{//AA实现IA接口
    //以下都是接口IUsb的方法实现
    @Override
    public Double get(String s) {
        return null;
    }
    @Override
    public void hi(Double aDouble) {

    }
    @Override
    public void run(Double r1, Double r2, String u1, String u2) {

    }
}

// 2.2 实现接口时,直接指定泛型接口的类型
//给 U 指定 Integer 给 R 指定了 Float
//所以,当我们实现 IUsb 方法时,会使用 Integer 替换 U, 使用 Float 替换 R
class BB implements IUsb{

    @Override
    public Float get(Integer integer) {
        return null;
    }

    @Override
    public void hi(Float aFloat) {

    }

    @Override
    public void run(Float r1, Float r2, Integer u1, Integer u2) {

    }
}

//3)没有指定类型,默认为Object
//建议直接写成 IUsb
class CC implements IUsb{//等价 class CC implements IUsb {}
    @Override
    public Object get(Object o) {
        return null;
    }

    @Override
    public void hi(Object o) {

    }

    @Override
    public void run(Object r1, Object r2, Object u1, Object u2) {

    }
}

4. 自定义泛型方法  562

4.1 基本语法

修饰符返回类型方法名(参数列表) {

}

4.2 注意细节

1.泛型方法,可以定义在普通类中,也可以定义在泛型类中

2.当泛型方法被调用时,类型会确定

3. public void eat(E e) {}, 修饰符后没有eat方法不是泛型方法,而是使用了泛型

代码在com.stulzl.generic_custom_method.包中

Generic_CustomMethod
package com.stulzl.generic_custom_method;

import java.util.ArrayList;

//自定义泛型方法 562
@SuppressWarnings({"all"})
public class Generic_CustomMethod {
    public static void main(String[] args) {
        Car car = new Car();
        //2. 当泛型方法被调用时,类型会确定
        car.fly("波音",180000);//当调用方法时,传入参数,编译器,就会确定泛型类型
        System.out.println("=======");
        car.fly(300, 100.1);//当调用方法时,就会确定泛型类型,这是的类型是Integer和Double

        //测试
        //T->String, R-> ArrayList
        Fish fish = new Fish<>();
        fish.hello(new ArrayList(), 11.3f);
    }
}
//1.泛型方法,可以定义在普通类中,也可以定义在泛型类中
class Car{//普通类
    public void run(){//普通方法

    }
    //说明 泛型方法
    //1.  就是泛型
    //2. 是提供给 fly 使用的
    public void fly(T t,R r){//泛型方法
        System.out.println(t.getClass());//类型//class java.lang.String
        System.out.println(r.getClass());//类型//class java.lang.Integer
    }
}
class Fish{//泛型类
    public void run() {//普通方法
    }
    public void eat(U u, M m) {//泛型方法
    }

    //3. public void eat(E e) {}, 修饰符后没有eat方法不是泛型方法,而是使用了泛型
    //说明
    //1. 下面 hi 方法不是泛型方法
    //2. 是 hi 方法使用了类声明的 泛型
    public void hi(T t){

    }

    //泛型方法,可以使用类声明的泛型,也可以使用自己声明泛型
    public void hello(R r,K k){
        System.out.println(r.getClass());//ArrayList
        System.out.println(k.getClass());//Float
    }
}

5. 自定义泛型类练习  563

练习:下面代码是否正确,如果有错误,修改正确,并说明输出什么?

自定义泛型

代码在com.stulzl.generic_custom_exercise01.包中

Generic_CustomExercise01
package com.stulzl.generic_custom_exercise01;

//自定义泛型类练习  563
//练习:下面代码是否正确,如果有错误,修改正确,并说明输出什么?
public class Generic_CustomExercise01 {
    public static void main(String[] args) {
        //T->String, R->Integer, M->Double
        Apple apple = new Apple<>();

        apple.fly(10);// 10会被自动装箱 类型Integer, 输出Integer
        apple.fly(new Dog());//类型Dog
    }
}
class Apple {//自定义泛型类

    public  void fly(E e) {  //泛型方法
        System.out.println(e.getClass().getSimpleName());//getSimpleName()方法可以只显示类型
    }

    //public void eat(U u) {}//错误,因为U没有声明

    public void run(M m) {
    } //ok
}

class Dog {
}

6.  泛型的继承和通配符  564

6.1 泛型的继承和通配符说明

1)泛型不具备继承性List

2)  :支持任意泛型类型

3) :支持A类以及A类的子类,规定了泛型的上限

4) :支持A类以及A类的父类,不限于直接父类,规定了泛型的下限

代码在com.stulzl.generic_extends.包中

Generic_Extends

package com.stulzl.generic_extends;

import java.util.ArrayList;
import java.util.List;

//泛型的继承和通配符说明  564
public class Generic_Extends {
    public static void main(String[] args) {
        //泛型不具备继承性
        //List list = new ArrayList();

        //举例说明下面三个方法的使用
        List list1 = new ArrayList<>();
        List list2 = new ArrayList<>();
        List list3 = new ArrayList<>();
        List list4 = new ArrayList<>();
        List list5 = new ArrayList<>();

        //如果是List c,可以接收任意类型的泛型类型
        printCollection1(list1);
        printCollection1(list2);
        printCollection1(list3);
        printCollection1(list4);
        printCollection1(list5);

        //List c: 表示 上限,即要接受AA或者AA子类才行
//        printCollection2(list1);//×//Object不是AA或者AA子类
//        printCollection2(list2);//×//String不是AA或者AA子类
        printCollection2(list3);//√//类型AA
        printCollection2(list4);//√//类型BB
        printCollection2(list5);//√//类型CC

        //List c: 支持AA类以及AA类的父类,不限于直接父类
        printCollection3(list1);//√//Object肯定是AA父类啊
        //printCollection3(list2);//×
        printCollection3(list3);//√//类型AA
        //printCollection3(list4);//×
        //printCollection3(list5);//×

    }

    // ? extends AA 表示 上限,可以接受 AA或者AA子类
    public static void printCollection2(List c) {
        for (Object object : c) {
            System.out.println(object);
        }
    }

    //说明: List 表示 任意的泛型类型都可以接受
    public static void printCollection1(List c) {
        for (Object object : c) { // 通配符,取出时,就是Object
            System.out.println(object);
        }
    }



    // ? super 子类类名AA:支持AA类以及AA类的父类,不限于直接父类,
    //规定了泛型的下限
    public static void printCollection3(List c) {
        for (Object object : c) {
            System.out.println(object);
        }
    }
}
class AA{

}
class BB extends AA{

}
class CC extends BB{

}
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月13日 0

暂无评论

推荐阅读
  TEZNKK3IfmPf   2023年11月15日   17   0   0 泛型java
  TEZNKK3IfmPf   2023年11月14日   30   0   0 泛型list
  TEZNKK3IfmPf   2024年04月19日   45   0   0 泛型java
  TEZNKK3IfmPf   2024年03月29日   62   0   0 list
  TEZNKK3IfmPf   2024年03月29日   34   0   0 listjava数组
  TEZNKK3IfmPf   2023年11月14日   52   0   0 listpytorch
TEZNKK3IfmPf