01_泛型

文章目录

泛型

参数化类型。

泛型的好处

  • 省去了类型强转的麻烦(比如:Object类、interface接口等都需要类型强转)
  • 运行期 遇到的问题转移到了编译期

泛型类

所谓泛型类, 就是把泛型定义在类上

格式

java 复制代码
class 类名<泛型类型1,...> {
}

注意事项

  • 默认类型
    • 定义了泛型,但是未写在<>中,会将其直接当做Object使用。
      eg:
java 复制代码
// 如果我们有一个使用了泛型写法的地方,  当我们使用这段代码的时候需要传入泛型, 
// 如果没有传, 这个泛型默认为Object类型

Holder2 holder3 = new Holder2(new AutoCar());
Object o = holder3.get();
  • 泛型的使用写法
    eg:
java 复制代码
// jdk1.5版本的时候写法: 前后尖括号都要指明类型
User<String> user1 = new User<String>();

// jdk1.7版本的时候, 对jdk1.5写法的简化, 本质上等价的
User<String> user1 = new User<>();
  • 泛型类可以定义多个泛型
    • 可以定义多个泛型,但不建议超过两个
    • 定义多个泛型,使用时,要么全部指定类型,要么全部不指定类型
      eg:
java 复制代码
class User<T, E>{
	T data;
	E info;
}

User<int, String> user = new User<>(2024 , "hello");
  • 定义了多个泛型,也可以不使用
    eg:
java 复制代码
class User3 <T, E, K> {
    T name;
    E age;
}
  • 泛型标识符

    • 使用单个大写字母。比如:E、T、K、V、R
      • E:element;
      • T:type;
      • K:key;
      • V:value;
      • R:return
  • 泛型必须使用引用类型,不能使用基本类型

    eg:

java 复制代码
User<int> user = new User<>(); // 报错: 泛型必须使用引用类型

User<Integer> user = new User<>();
  • 泛型类, 定义了泛型之后, 泛型的作用域

      1. 在自己的类中间,会起作用。但是在子类中,不起作用。
      1. 在自己的类上面(指public class User<T> extends Person<E, E>),就是在自己的类定义这一行,可以使用这个泛型。
  • 泛型在父子继承关系上的表现

    • 如果继承时,未指定父类泛型 ,则为默认类型。Object
      • class Son1 extends Father{}
    • 如果继承时,指定了父类类型 ,则为指定类型,无论子类定义泛型与否。
      • class Son2 extends Father<String>{} --> 父类变量类型为String
      • class Son3<E> extends Father<Integer>{} --> 父类变量类型为Integer
    • 如果继承时,传入了子类指定的泛型 ,则父类与子类变量类型一致
      • class Son4<E> extends Father<E>{}

eg:

java 复制代码
public class Father<T> {
    T ft;
}

class Son1 extends Father {

}

class Son2 extends Father<Integer> {

}

class Son3<E> extends Father<String> {

}

class Son4<T> extends Father<T> {

}

class Son5<E> extends Father<E>{

}


public class FatherDemo {
    public static void main(String[] args) {

        // 定义类的时候,没有指定Father的类型,所有默认类型为Object
        Son1 son1 = new Son1();
        Object ft = son1.ft;

        // Son2 定义时,未指定泛型,指定了 Father泛型为Integer,所以ft为Integer
        Son2 son2 = new Son2();
        Integer ft1 = son2.ft;

		// 如果继承时,指定了父类类型,则为指定类型,无论子类定义泛型与否
        Son3<Integer> son3 = new Son3();
        String ft4 = son3.ft;

        // Son4 定义时,指定泛型T,指定了 Father泛型为T,所以ft类型和子类一致
        Son4<Integer> son4 = new Son4<>();
        Integer ft2 = son4.ft;

        // Son5 指定E,表示与符号无关
        Son5<String> son5 = new Son5<>();
        String ft3 = son5.ft;
    }
}

泛型接口

所谓泛型接口, 就是把泛型定义在接口上

格式

java 复制代码
interface 接口名<泛型类型1...>

举例

java 复制代码
interface Player<T,E> {
    E play(T data);
}


// 在什么时候能指定它的类型?

// 1. 实现接口的时候没有指定类型,则泛型的类型为默认的Object
class YoungPlayer implements Player{

    @Override
    public Object play(Object data) {
        return null;
    }
}

// 2. 如果实现时,指定为什么类型,则是什么类型
class OldPlayer implements Player<String, Integer>{

    @Override
    public Integer play(String data) {
        return null;
    }
}

// 3. 如果子类也有泛型,则与子类一致
class BigPlayer<K,V> implements Player<K,V>{

    @Override
    public V play(K data) {
        return null;
    }
}

eg:

java 复制代码
// 转换器的接口,把一个类型转换成另外一个类型
interface Converter<T, R> {
    R converter(T t);
}

public class String2Date implements Converter<String, Date> {

    @Override
    public Date converter(String s) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date parse = null;
        try {
            parse = simpleDateFormat.parse(s);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        return parse;
    }
}

泛型方法

所谓泛型方法, 把泛型定义在方法上

格式

java 复制代码
 <泛型类型> 返回类型 方法名(泛型类型...)

eg:

java 复制代码
public class Demo {
    public static void main(String[] args) {
        A a = new A();
        Integer t = a.getT(10);
        String s = a.getT("hello");
    }
}

class A{
    <T> T getT(T data){
        return data;
    }
}

注意事项

方法上没有定义泛型,只是使用了泛型,不叫泛型方法。


泛型的通配

(看到源码,能明白含义即可。)

泛型不允许协变, 又想产生类似协变的效果, 又不想引入协变带来的问题(类型不匹配问题)

协变与逆变

  • 协变就是,允许接收该类及该类的子类
    • 数组是支持协变的。
  • 逆变就是,允许接收该类及该类的父类

格式

  • 泛型通配符<?>
    • 任意类型,如果没有明确,那么就是Object以及任意的Java类了
    • public void print(User<?> user)
  • ? extends E
    • 向下限定,E及其子类
    • public void print(User<? extends Number> user)
  • ? super E
    • 向上限定,E及其父类

泛型的擦除

  • Java中的泛型并不是真的泛型, Java的泛型只存在于编译之前
  • 当Java中的泛型编译之后 , 会把泛型编译成Object以及类型强转

相关推荐
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ3 分钟前
MyBatis执行完sql后,返回的数值代表的意思
java·开发语言
CodeClimb34 分钟前
【华为OD-E卷-寻找密码 100分(python、java、c++、js、c)】
java·python·华为od
爱上语文37 分钟前
宠物管理系统:Service层
java·开发语言·宠物
水w1 小时前
【项目实践】SpringBoot Nacos配置管理 map数据
java·服务器·开发语言·spring boot·nacos
@菜鸟进阶记@1 小时前
SpringBoot核心:自动配置
java·spring boot·后端
瓜牛_gn1 小时前
苍穹外卖项目Day02代码结构深度解析
java·spring
汤姆yu1 小时前
基于springboot的健身俱乐部网站系统
java·spring boot·后端·健身房·俱乐部
喵手1 小时前
Java 实现日志文件大小限制及管理——以 Python Logging 为启示
java·开发语言·python
huapiaoy1 小时前
JavaSE---String(含一些源码)
java·linux·前端
LIZHUOLONG11 小时前
用C语言实现线程池
java·c语言·算法