这是原有的泛型接口和具体的某一个实现类
//泛型接口
public interface SaveService<T> {
void save(List<T> saveList);
}
//具体实现类
public class UserSaveServiceImpl implements SaveService<User>{
@Override
public void save(List<User> saveList) {
//...
}
}
处于一些原因,必须把泛型接口改成非泛型接口...(很奇葩的问题,但是必须改掉接口的泛型)
public interface SaveService {
<T> void save(List<T> saveList);
}
于是想把泛型方法续上...强行续...
public class UserSaveServiceImpl implements SaveService{
@Override
public <T> void save(List<T> saveList) {
}
//期望还能续上指定的类型 User
}
结果也很明显,具体实现类上的类型算是完蛋啦,请问如何能满足这样的奇葩需要么(能满足么...
1
donggexiongdi 2021-12-30 23:18:15 +08:00
看下 hashmap
|
2
RiceMarch OP @donggexiongdi Map 也是泛型接口来着...public class HashMap<K,V> extends AbstractMap<K,V>,我就是不想加类的泛型
|
3
Jooooooooo 2021-12-31 00:47:21 +08:00 1
没看懂...
而且你可以再想想是否提了 A/B 问题 |
4
Macolor21 2021-12-31 01:48:11 +08:00 via iPhone 1
续上类型是什么意思?
你写的代码里写了一个泛型方法,那这个方法就是泛型的,它的约束范围只在方法级别。 你的问题描述不清楚,但有两种走向: 1. 你想实现类级别泛型,所有方法的返回类型等都是 User (只能泛型类 /接口) 2. 你想实现 save 的泛型。(你已经写出了泛型方法,但你没指定泛型类型,在实现类还是 T ,需要将 T 改成 User ,就可以了) 所以我还是不懂你的问题,你写的第二个实现中没有指定泛型类型,你的方法还是泛型方法。 在你的第一个实现中你指定了泛型 User 。该类继承 T 的方法都是泛型。 如果你是想用户使用 UserImpl 时,只能用 User 类型,那你把 T 改成 User 不就可以了? 方法调用层只能看到 List<User>的入参 |
5
wellsc 2021-12-31 02:44:31 +08:00 via iPhone
@Jooooooooo x y?
|
6
RedrumSherlock 2021-12-31 06:11:28 +08:00 via Android
什么叫续上指定的类型?调用方法的时候不就把类型传进去了么?
|
7
hingbong 2021-12-31 07:36:15 +08:00 via Android
你是想接口方法是带泛型的,实现类不是?不行的,你想想你的需求在
|
8
hingbong 2021-12-31 07:37:56 +08:00 via Android
你是想接口方法是带泛型的,实现类不是?不行的,结合多态来看,你想想你的需求在使用接口调用的时候怎么确定类型,除非在实现类判断类型,传参不对就报错
|
9
zhilincom 2021-12-31 07:47:01 +08:00
不让用泛型是公司不让用吗?要么遵守要么跳槽。如果不是干嘛给自己找不自在?
|
10
Ariver 2021-12-31 08:11:00 +08:00 1
之前的实现,user 是被范型接口确定的,你的类,实现了这个,那么类型也就确定了。所以,方法上的,类型,也是确定的。
你想的实现,接口不是范型的,那么实现类上也就没有那个 T 的类型了。 那么,范型方法上的类型,就是在方法调用的时候根据传入的类型来决定的。 ps.一般来说,这种范型方法我们通常做法是<? extends T>. 这样在你的 save 方法内,才可以使用 T 这个父类上的方法,不然没啥用。 |
11
yidinghe 2021-12-31 08:20:09 +08:00 via Android
接口改成这样,那就写一个唯一的实现类算了
|
12
kujio 2021-12-31 09:13:28 +08:00
可以试试不用泛型,用一个被继承的实体抽象类来代替泛型 T
|
13
RiceMarch OP @zhilincom 不是 是我另外的同事要在一个 list 塞这个接口的不同实现类 导致一个 list 有多种实现类,静态扫描被拒绝 所以他要求我把接口的泛型抹掉 哎 无奈
|
14
cppc 2021-12-31 09:43:11 +08:00
@RiceMarch 这难道不是你同事的问题,List<SaveService<?>> 不行?如果不用泛型,那么是不是会有 SaveUserService,SaveXxxService ,这样 List 就能装下你得接口了?
|
15
timethinker 2021-12-31 09:50:36 +08:00
根据里氏替换原则,子类实例指向父类指针,也就是说假如有一个 SubUser extends User ,此时 List<User>是可以 add 这个 SubUser 实例的吧。如果想要返回 List<SubUser>,可以把方法签名改为 List<? extends User>。
|
16
timethinker 2021-12-31 09:56:36 +08:00
@qwe520liao 这里说反了,应该是父类指针既可以指向父类实例,也可以指向子类实例。虽然 Java 没有指针的概念,但是这里相当于引用。
|
17
wolfie 2021-12-31 10:02:23 +08:00
X Y +1
|
18
aguesuka 2021-12-31 10:13:19 +08:00
@RiceMarch XY 问题, 你只需将
//泛型接口 public interface SaveService<T> { void save(List<T> saveList); } 改成 //泛型接口 public interface SaveService<T> { void save(List<? extends T> saveList); } |
19
aguesuka 2021-12-31 10:19:50 +08:00
甚至是新的 method
public interface SaveService<T> { void save(List<? extends T> saveList); void <T> saveAllWithoutTyping(List<T> saveList); } |
20
goalidea 2021-12-31 11:47:48 +08:00
如果你确定该实现类型是 User 强转过来就行了
|
21
Joker123456789 2021-12-31 13:00:23 +08:00 1
按照你现在的写法,你传进来什么类型,T 就是什么类型,但是无法 在创建对象的时候 约束 这个方法只能接收什么类型。
既然如此,不如 把 T 去掉咯,只要是 List 就收。 如果 你想 实现在创建对象的时候 约束 这个方法只能接收什么类型,那么 接口上的 <T> 是必须保留的,也就是必须用你一开始的那种方式。 如果你现在遇到的需求,用泛型是 最佳的方案,那你可以去跟 不让你用泛型的那个人 商量一下 怎么解决。 如果不用泛型问题也不大,那么干脆去掉泛型把,因为你现在的这个做法 体现不出泛型的意义。 |
22
aliveyang 2021-12-31 15:51:35 +08:00
看不懂问题
|
23
RiceMarch OP @aguesuka 其实本质上是同事的奇葩想法 想把 interface SaveService<T>的这个 T 去掉我今天已经拒绝了他这个要求 hhhh
|
24
RiceMarch OP @Joker123456789 确实是的 今天已经和她商量过了 List 的类型肯定还是要的 不然静态检查直接被拦截了 hhhhh 还是按照第一种继续做了
|
25
okou19900722 2022-01-07 11:34:58 +08:00
很简单,因为 java 里的泛型是擦除的。
目前我了解的可以通过反射获取到泛型的,似乎只有子类实现父类时,传给父类的泛型可以获取,比如 List<String> list = new ArrayList<String>(); 这样写,拿不到,因为泛型是 ArrayList 上的,但 List<String> list = new ArrayList<String>(){}; 这样写就可以拿到泛型,这是因为这实际上是生成了一个 ArrayList 子类的匿名类的对象。 具体的原因,我说不清楚,写过 gson 的,应该对 TypeToken 很熟悉,基本都是 new TypeToken<xxxx>(){}的写法 |