我是靠谱客的博主 落后书包,这篇文章主要介绍Java 泛型中 <? extends T> 与 <? super T> 的区别1、? 和 T 是什么?2、代码示例,现在分享给大家,希望可以做个参考。

1、? 和 T 是什么?

? 是通配符(wildcard,记住这个单词,这样在报错时就知道说的是 ? 通配符),T 是类型变量。

  • 根据字面意思,<? extends T> 表示 任何继承自类型 T 的类型<? super T> 表示 任何是类型 T 的超类的类型

? extend/super Xx 不能用于声明处。
下面是用于表达式的正确例子:

复制代码
1
2
3
Plate<? super Fruit> p = new Plate<Fruit>(new Fruit()); Plate<? extend Fruit> p1;

下面是用于声明处的错误例子:

复制代码
1
2
public class Fruit {} public class Plate<? extends Fruit> {} // 报错 Unexpected wildcard
  • T 则与问号不同,它只能用于声明处。<T extends Fruit> 表示声明一个类型变量 T,它是 Fruit 的一个具体子类不能写 <T super Fruit>,因为这样是没有任何意义的。原因是所有泛型在编译时都会被擦除,T 所代表的是一个 Fruit 的超类,但是具体是哪个类却是在运行时被决定的,编译器为了类型安全,只能做最大限度的包容,因此所有的 T 类型都会在编译器变为 Object。所以,写 <T super Fruit> 等同于写 <Object>,因此不支持 <T super Xx>

2、代码示例

2.1 定义实体

水果-所有水果父类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.ybw.generic.dto; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.math.BigDecimal; /** * 水果 * * @author ybw * @version V1.0 * @className Fruit * @date 2022/11/21 **/ @Data @AllArgsConstructor @NoArgsConstructor public class Fruit { /** * @author: ybw * @date: 2022/11/21 **/ private Long id; /** * 价格 * * @author: ybw * @date: 2022/11/21 **/ private BigDecimal price; }

子类-苹果、桔子

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.ybw.generic.dto; import lombok.Data; import lombok.EqualsAndHashCode; /** * @author ybw * @version V1.0 * @className Apple * @date 2022/11/21 **/ @Data @EqualsAndHashCode(callSuper = true) public class Apple extends Fruit { private String colour; public Apple(Fruit fruit, String colour) { super(fruit.getId(),fruit.getPrice()); this.colour = colour; } }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.ybw.generic.dto; import lombok.Data; import lombok.EqualsAndHashCode; import java.math.BigDecimal; /** * @author ybw * @version V1.0 * @className Orange * @date 2022/11/21 **/ @Data @EqualsAndHashCode(callSuper = true) public class Orange extends Fruit { /** * 重量 * * @author: ybw * @date: 2022/11/21 **/ private BigDecimal weight; public Orange(Fruit fruit, BigDecimal weight) { super(fruit.getId(),fruit.getPrice()); this.weight = weight; } }

盘子

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.ybw.generic.dto; import lombok.AllArgsConstructor; import lombok.Data; /** * @author ybw * @version V1.0 * @className Plate * @date 2022/11/21 **/ @Data @AllArgsConstructor public class Plate<T> { private T t; }

2.2 实现类(泛型)

接口

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.ybw.generic.service; import com.ybw.generic.constant.Type; import com.ybw.generic.dto.Fruit; import com.ybw.generic.dto.Plate; /** * @author ybw * @version V1.0 * @className FruitService * @date 2022/11/21 **/ public interface FruitService { /** * 买水果 * * @param type * @methodName: buyFruit * @return: java.util.List<com.ybw.generic.dto.Fruit> * @author: ybw * @date: 2022/11/21 **/ <T extends Fruit> Plate<T> buyFruit(Type type); }

实现类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.ybw.generic.service.impl; import com.ybw.generic.constant.Type; import com.ybw.generic.dto.Apple; import com.ybw.generic.dto.Fruit; import com.ybw.generic.dto.Orange; import com.ybw.generic.dto.Plate; import com.ybw.generic.service.FruitService; import java.math.BigDecimal; /** * @author ybw * @version V1.0 * @className FruitServiceImpl * @date 2022/11/21 **/ public class FruitServiceImpl implements FruitService { @Override public <T extends Fruit> Plate<T> buyFruit(Type type) { switch (type) { case APPLE -> { Apple apple = new Apple(new Fruit(1L, BigDecimal.TEN), "红色"); return (Plate<T>) new Plate<>(apple); } case ORANGE -> { Orange orange = new Orange(new Fruit(2L, BigDecimal.ONE), BigDecimal.TEN); return (Plate<T>) new Plate<>(orange); } default -> { } } return new Plate<>(null); } }

2.3 测试

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.ybw.generic.service; import com.alibaba.fastjson2.JSON; import com.ybw.generic.constant.Type; import com.ybw.generic.dto.Apple; import com.ybw.generic.dto.Orange; import com.ybw.generic.dto.Plate; import com.ybw.generic.service.impl.FruitServiceImpl; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; @Slf4j class FruitServiceTest { @Test void buyFruit() { FruitService fruitService=new FruitServiceImpl(); Plate<Apple> applePlate=fruitService.buyFruit(Type.APPLE); log.info("applePlate:{}", JSON.toJSONString(applePlate)); Plate<Orange> orangePlate=fruitService.buyFruit(Type.ORANGE); log.info("orangePlate:{}", JSON.toJSONString(orangePlate)); } }

最后

以上就是落后书包最近收集整理的关于Java 泛型中 <? extends T> 与 <? super T> 的区别1、? 和 T 是什么?2、代码示例的全部内容,更多相关Java内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(63)

评论列表共有 0 条评论

立即
投稿
返回
顶部