java实例化泛型_Java学习1:泛型类的实例化
学习java的学习方法在平时编程的过程中,为了尽可能多的兼容更多的类型,通常会使⽤到泛型。虽然,使⽤泛型能带来很多的好处,⽐如最明显的就是省去了强制类型转换。但同时也带来了⼀些⿇烦。例如,如果代码中有下⾯这样的需求
public class Practice {
T mParam;
public Practice() {
mParam = new T();//报错 Type parameter 'T' cannot be instantiated directly
}
}
产⽣这种错误的原因主要有两点
1.泛型擦除
2.编译器不知道该类型是否有默认的构造器
通常为了使⽤泛型,同时还要避免这样的问题出现,会花很多时间寻可替代⽅案。有没有同时兼顾的办法呢?答案是肯定的。利⽤Class 对象就可以达到想要的实现的效果,看代码
public class Practice {
T mType;
public Practice(Class clz) {
mType = wInstance(); //为了⽅便,这⾥省略了 atch代码块
}
static class Trainer {
public void print() {
System.out.println("Trainer创建成功");
}
}
public static void main(String[] args) {
Practice trainerPractice = new Practice<>(Trainer.class);
Trainer trainer = trainerPractice.mType;
trainer.print();
}
}
输出结果:Trainer创建成功
看到这有没有点⼩激动,既使⽤了泛型,同时创建了⼀个“泛型实例”。不过,先别急着激动,当把⾃⼰定义的Trainer类替换成Integer上述代码就会报错了,原因是Integer没有任何默认的构造器。这个错误不是 在编译期捕获的,所以当我们使⽤Integer运⾏的时候就会报错
Caused by: java.lang.NoSuchMethodException: java.lang.Integer.()
at java.Constructor0(Class.java:3082)
at java.wInstance(Class.java:412)
... 7 more
从报错信息也可以看出,不到初始化的⽅法。
带着这个问题,我们观察⼀下上⾯最初提出的解决问题的⽅案,不论是什么类型,都将实例化的过程都⽤了同⼀种的实例化⽅法
mType = wInstance();
这样做,即便不使⽤Integer,当我们需要把某个⾃定义的类默认构造⽅法声明为private时,上⾯的⽅法也不适⽤了。那怎样解决这个问题呢?答案就是java编程的六⼤基本原则之⼀的⾯向接⼝编程。接⼝的好处就是把具体实现分割开,针对不同的需求,各⾃实现⾃⼰想要的结果,互相之间不⼲扰。
有了思路,下⾯就开始解决这个问题。⾸先声明⼀个接⼝,接⼝⾥声明⼀个⽅法,此⽅法⽤来创建泛型所代表类的实例
public interface Creator {
T create();
}
这⾥还是以⾃定义的Trainer类实例化为例。创建⼀个⽤来把泛型类和实例化结果关联起来的⼯⼚类,⼯⼚类不关⼼具体的实例化过程,它只负责将实例化结果赋值给泛型类。⼯⼚类的构造⽅法是⼀个泛型⽅法,泛型的边界是接⼝Creator,同时构造⽅法的参数是实现了Creator接⼝的⼦类。在⼦类的create()⽅法⾥是具体的类实例化过程。
public class Factory {
private T t;
public > Factory(C creator) {
t = ate();
}
}
在Factory类⾥,通过调⽤实现了Creator接⼝⼦类的create()⽅法创建实例。接下来,创建⼀个TrainerCreator类来实现Creator接⼝
public class TrainerCreator implements Creator {
@Override
public Trainer create() {
return new Trainer();
}
public static void main(String[] args) {
Factory factory = new Factory<>(new TrainerCreator());
Trainer trainer = T();
System.out.String());
}
}
输出结果:Trainer
为了⽅便我把Trainer类的代码也贴出来
public class Trainer {
@Override
public String toString() {
return "Trainer";
}
}
⾄此,改进版的代码就完成了。可以看到,类的实例化也就是new动作放在了具体的实现类⾥,⽽Factory的作⽤类似于适配器⼀样,它负责将Creator接⼝实现类的create()⽅法返回的类实例赋值给泛型类。这样做,⼤⼤降低了代码的耦合度。假如,此时需要⼀个Integer类型的值。那么只需要实现Cr
eator接⼝创建⼀个新的⽤于创建Integer实例的实现类就可以了
public class IntegerCreator implements Creator {
@Override
public Integer create() {
return 1;
}
public static void main(String[] args) {
Factory factory = new Factory<>(new IntegerCreator());
Integer integer = T();
System.out.String());
}
}
输出结果:1
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论