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以及类型强转

相关推荐
激流丶6 分钟前
【Kafka 实战】如何解决Kafka Topic数量过多带来的性能问题?
java·大数据·kafka·topic
Themberfue10 分钟前
Java多线程详解⑤(全程干货!!!)线程安全问题 || 锁 || synchronized
java·开发语言·线程·多线程·synchronized·
让学习成为一种生活方式27 分钟前
R包下载太慢安装中止的解决策略-R语言003
java·数据库·r语言
晨曦_子画32 分钟前
编程语言之战:AI 之后的 Kotlin 与 Java
android·java·开发语言·人工智能·kotlin
南宫生1 小时前
贪心算法习题其三【力扣】【算法学习day.20】
java·数据结构·学习·算法·leetcode·贪心算法
Heavydrink1 小时前
HTTP动词与状态码
java
ktkiko111 小时前
Java中的远程方法调用——RPC详解
java·开发语言·rpc
计算机-秋大田2 小时前
基于Spring Boot的船舶监造系统的设计与实现,LW+源码+讲解
java·论文阅读·spring boot·后端·vue
神里大人2 小时前
idea、pycharm等软件的文件名红色怎么变绿色
java·pycharm·intellij-idea
小冉在学习2 小时前
day53 图论章节刷题Part05(并查集理论基础、寻找存在的路径)
java·算法·图论