现在有一个需求:写一个打印类,用来打印不同类型的数据
//类1 :打印Integer类型的数据
public class IntegerPrint {
Integer content;
public void Integer(Integer content) {
this.content = content;
}
public void print(){
System.out.println(content);
}
}
//类2 :打印String类型的数据
public class StringPrint {
String content;
public void Integer(String content) {
this.content = content;
}
public void print(){
System.out.println(content);
}
}
如上述代码,但是我们发现如何有很多不同的类型进行打印,则需要创建很多个类,这样代码会非常冗余
而这个时候,就可以使用泛型来解决这个问题!
//<>就代表泛型,里面的T就代表传入的类型
public class Print<T> {
T content;
public Print(T content) {
this.content = content;
}
public void print(){
System.out.println(content);
}
}
比如上述的代码,肯定不能让使用者随意传入类型,那我们如何进行约束呢?
extend
约定上边界super
约定下边界假设 XiaoMi
, HuaWei
类继承 Phone
类
public class Main
就约束了这个类传入的只能是Phone类或者Phone类的子类
public class Main
则是约束了这个类传入的只能是XiaoMi类或者XiaoMi类的父类(比如Phone类)
注意:后面同样可以跟接口,不过接口要放在类的后面,比如public class FanXing
,这个时候要求的不仅仅是继承于Phone类还要求实现了Comparable接口
//假设我们想打印list里的数据
//类1:List里的数据为Integer类型
public class IngerPrint {
public static void print(List<Integer> list) {
System.out.println(list);
}
}
//类2:List里的数据为String类型
public class StringPrint {
//假设我们想打印list里的数据
public static void print(List<String> list) {
System.out.println(list);
}
}
尝试优化,不让代码那么冗余,我们直接使用Object类型
为什么呢?因为List
和 List
分别是一个整体,是不同的类型,那我们应如何解决呢?使用通配符即可
public class FanXing {
public static void main(String[] args) {
List<Object> list = new ArrayList<>();
list.add(123);
list.add("abcd");
String str = (String) list.get(0);
System.out.println(str);
}
}
//会报错:ClassCastException
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at FanXing.main(FanXing.java:13)
这样的时候在编译阶段是没有问题的,但是在运行时发生了报错,是因为泛型是在编译阶段进行类型检查的,而不是运行时。
通常不建议这样使用,会带来运行安全问题,并且这样的代码后期维护很麻烦。