java泛型的使用
泛型的产生机制就是放什么类型的数据进去,取出来的就是什么类型,而不用进行类型转换
泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
泛型是在编译阶段有效
Java 泛型只在编译阶段有效,即在编译过程中,程序会正确的检验泛型结果。而编译成功后,class 文件是不包含任何泛型信息的
使用泛型可以指代任意对象类型;
泛型类
public class CC<T>{
private T ob;
public CC(T ob) {
super();
this.ob = ob;
}
public T getOb() {
return ob;
}
public void setOb(T ob) {
this.ob = ob;
}
/**
* 打印T的类型
*/
public void print(){
System.out.println("T的实际类型是:"+ob.getClass().getName());
}
}
// begin test CC
CC<Integer> cc=new CC<Integer>(1);
cc.print();
int icc=cc.getOb();
System.out.println("i3="+icc);
CC<String> cc2=new CC<String>("我是泛型,好简单啊");
cc2.print();
String icc2=cc2.getOb();
System.out.println("s2="+icc2);
// end test CC
泛型方法
public class Box<T> {
private T box;
public T getBox(T t){
this.box = t;
return t;
}
public void getType(){
System.out.println("T的实际类型为:"+box.getClass().getName());
}
public static void main(String[] args) {
Box box = new Box();
System.out.println(box.getBox(1));
box.getType();
System.out.println(box.getBox("Tom"));
box.getType();
}
}
T的实际类型为:java.lang.Integer<br>
Tom
T的实际类型为:java.lang.String
返回值为任意类型的泛型
public static <T> void f(T t){
System.out.println("T的类型是:"+t.getClass().getName());
}
public static void main(String[] args) {
f("");
f(1);
f(1.0f);
f(new Object());
}
泛型通配符
在泛型中,我们可以用 ? 来代替任意类型
public List wildCard(List<?> list){
return list;
}
public static void main(String[] args) {
GenericTest gt = new GenericTest();
//构造一个 Interger 类型的集合
List<Integer> integer = new ArrayList<Integer>();
integer.add(1);
System.out.println(gt.wildCard(integer));
//构造一个 String 类型的集合
List<String> str = new ArrayList<String>();
gt.wildCard(str);
//构造一个 Object 类型的集合
List<Object> obj = new ArrayList<Object>();
obj.add(1);
obj.add("a");
System.out.println(gt.wildCard(obj));
//构造一个 任意类型的 集合,这和 List<Object> 存放数据没啥区别
List list = new ArrayList();
gt.wildCard(list);
}
private static void take(Demo<?> a){
a.print();
}
public static void main(String[] args) {
Demo<Dog> demo=new Demo<Dog>(new Dog());
take(demo);
Demo<Cat> demo2=new Demo<Cat>(new Cat());
take(demo2);
}
泛型的上限和下限
①、上限: 语法(? extends className),即只能为 className 或 className 的子类
//通配符的下限,只能是 Number 或 Number的子类
public List wildCard(List<? extends Number> list){
return list;
}
public static void main(String[] args) {
GenericTest gt = new GenericTest();
//构造一个 Interger 类型的集合
List<Integer> integer = new ArrayList<Integer>();
integer.add(1);
System.out.println(gt.wildCard(integer));
//构造一个 String 类型的集合
List<String> str = new ArrayList<String>();
//gt.wildCard(str); //编译报错
//构造一个 Object 类型的集合
List<Object> obj = new ArrayList<Object>();
obj.add(1);
obj.add("a");
//System.out.println(gt.wildCard(obj)); //编译报错
}
下限: 语法(? super className),即只能为 className 或 className 的父类
//通配符的上限,只能是 Number 或 Number的父类
public List wildCard(List<? super Number> list){
return list;
}
public static void main(String[] args) {
GenericTest gt = new GenericTest();
//构造一个 Interger 类型的集合
List<Integer> integer = new ArrayList<Integer>();
integer.add(1);
//System.out.println(gt.wildCard(integer)); //编译报错
//构造一个 String 类型的集合
List<String> str = new ArrayList<String>();
//gt.wildCard(str); //编译报错
//构造一个 Object 类型的集合
List<Object> obj = new ArrayList<Object>();
obj.add(1);
obj.add("a");
System.out.println(gt.wildCard(obj));
}
public class Animal {
public void print(){
System.out.println("动物");
}
}
public class Dog extends Animal{
public void print(){
System.out.println("Dog");
}
}
public class Cat extends Animal{
public void print(){
System.out.println("Cat");
}
}
public class Demo <T extends Animal>{
private T ob;
public T getOb() {
return ob;
}
public void setOb(T ob) {
this.ob = ob;
}
public Demo(T ob) {
super();
this.ob = ob;
}
public void print(){
System.out.println("T的类型是:"+ob.getClass().getName());
}
}
public class Test {
public static void main(String[] args) {
Demo<Dog> demo=new Demo<Dog>(new Dog());
Dog dog=demo.getOb();
dog.print();
Demo<Cat> demo2=new Demo<Cat>(new Cat());
Cat cat=demo2.getOb();
cat.print();
Demo<Animal> demo3=new Demo<Animal>(new Animal());
}
}
不能用基本类型来定义泛型,如 int、float
如果使用 ? 接收泛型对象时,则不能设置被泛型指定的内容
List<?> list = new ArrayList<>();
list.add("aa"); //错误,无法设置
泛型方法的定义与其所在的类是否是泛型类是没有任何关系的,所在的类可以是泛型类,也可以不是泛型类
泛型类没有继承关系,即String 为 Object 类型的子类,则 List<String> 是 List<Object> 的子类这句话是错误的
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
String[] str = {"a","b","c"};
List listStr = Arrays.asList(str);
System.out.println(listStr.size());//3
int[] i = {1,2,3};
List listI = Arrays.asList(i);
System.out.println(listI.size());//1
上面的结果第一个listStr.size()==3,而第二个 listI.size()==1。这是为什么呢?
我们看源码,在 Arrays.asList 中,方法声明为 <T> List<T> asList(T... a)。该方法接收一个可变参数,并且这个可变参数类型是作为泛型的参数。我们知道基本数据类型是不能作为泛型的参数的,但是数组是引用类型,所以数组是可以泛型化的,于是 int[] 作为了整个参数类型,而不是 int 作为参数类型。
所以将上面的方法泛型化补全应该是:
String[] str = {"a","b","c"};
List<String> listStr = Arrays.asList(str);
System.out.println(listStr.size());//3
int[] i = {1,2,3};
List<int[]> listI = Arrays.asList(i);//注意这里List参数为 int[] ,而不是 int
System.out.println(listI.size());//1
Integer[] in = {1,2,3};
List<Integer> listIn = Arrays.asList(in);//这里参数为int的包装类Integer,所以集合长度为3
System.out.println(listIn.size());//3