1、?
和 T
是什么?
?
是通配符(wildcard,记住这个单词,这样在报错时就知道说的是 ? 通配符),T
是类型变量。
- 根据字面意思,
<? extends T>
表示 任何继承自类型T
的类型,<? super T>
表示 任何是类型T
的超类的类型。
? extend/super Xx
不能用于声明处。
下面是用于表达式的正确例子:复制代码1
2
3Plate<? super Fruit> p = new Plate<Fruit>(new Fruit()); Plate<? extend Fruit> p1;
下面是用于声明处的错误例子:
复制代码1
2public 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
31package 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
19package 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
26package 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
15package 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
23package 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
33package 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
20package 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内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复