如何使用泛型类,类型如何实例化,我们只需要保证传入的实参类型和泛型参数类型相同即可。
//正常用法 Person<String> s1 = new Person<String>("张三"); //jdk7.0后可以省略后面的参数类型 Person<String> s2 = new Person<>("张三"); s2.run(); //当然泛型的定义是可以帮助我们按照某种规则去做事,如果不做限制,也不会编译错误,但泛型就毫无意义了 Person t = new Person(111); t.run(); //泛型的类型不能是八大基本类型,下面会编译出错 Person<int> s = new Person<>(1); 四. 泛型接口泛型接口和泛型类的定义基本一致,定义如下:
public interface Person<T> { public T parent(); public String eat(); }当我们定义了一个类要实现该接口时,那么该类的泛型类型必须和接口类的泛型类型一致,未传递实参的情况下,继续使用泛型类型T,传递了实参的情况下,泛型类型必须使用实参类型
public class Teacher<T> implements Person<T> { @Override public T parent() { return null; } @Override public String eat() { return null; } } //Teacher不必再定义类型了,因为泛型类型在Person处已经定义好了 public class Teacher implements Person<Integer> { //这里的返回类型必须为Integer,否则必须出错 @Override public Integer parent() { return null; } @Override public String eat() { return null; } } 五. 泛型方法泛型方法可以定义在普通类和泛型类中,比如泛型类更为常用,一般能用泛型方法解决的问题优先使用泛型方法而不使用泛型类,类型变量放在修饰符的后面,如public static ,public final等的后面。
public class Teacher { public static <T> T println(T t){ System.out.println(t); return t; } }调用很简单,很一般方法调用是一样的,更方便的是类型不像一般方法做了限定。
String s = Teancher.println("str");另外需要说明的是,定义在泛型类中的泛型方法的泛型变量之间是没有关系的,如这样的代码
public class Teacher<T> { T teacher; public Teacher(T t){ this.teacher = t; } public <T> T println(T t){ System.out.println(t); return t; } } Teacher<String> teacher = new Teacher<>("张三"); Integer in = teacher.println(123456);类泛型类型为String,方法的泛型类型为Integer,虽然都是用T来表示的。
同时关于泛型方法需要说明的是:
在修饰符public xx与方法名之间非常重要,有< T >这样的才算是泛型方法;仅仅使用了泛型变量并不算是泛型方法。
六. 限定类型变量不论是泛型类还是泛型方法,目前来说其实都是没有做类型限定,无论我们传递什么样类型的变量进去都可以,因为我们在处理逻辑中并没有使用到该类型特有的东西(成员变量、方法等)。假如我们想传递的参数类型仅仅是某个大类(父类)下面的一些小类(子类),那么怎么做呢?
public class ArrayFlag { public static <T> T getMax(T[] array){ if(array == null || array.length == 0){ return null; } T maxValue = array[0]; for(int i = 0; i < array.length; i++){ if(array[i].compareTo(maxValue) > 0){ maxValue = array[i]; } } return maxValue; } }大家也看到了我们在getMax方法中使用了compareTo方法进行比较,但如果我们传入的类型T没有compareTo方法呢,岂不是要报错,因此我们需要做限定,只要限定了是Comparable接口的必然具备compareTo方法,那么改造后就成了这样
public class ArrayFlag { public static <T extends Comparable> T getMax(T[] array){ if(array == null || array.length == 0){ return null; } T maxValue = array[0]; for(int i = 0; i < array.length; i++){ if(array[i].compareTo(maxValue) > 0){ maxValue = array[i]; } } return maxValue; } }同时需要说明的是,此处用的是extends关键字,extends在这里是表示的是绑定了Comparable接口及其子类型,是“绑定、限定”的意思,非“继承”的意思,后面也可以是接口或者类,如果有多个限制,可以使用&分隔,如:
public static <T extends Comparable & Serializable> T getMax(T[] array) 七. 泛型通配符举个例子,定义了一个书籍类和一个小说类
//定义了一个书籍类 public class Book {} //定义了一个小说书籍类继承书籍类 public class Novel extends Book {}我们再定义一个书柜类用来装书籍以及小说
//定义了一个书柜类用来装书 public class Bookcase<T> { T b; public Bookcase(T t){ this.b = t; } public void set(T t) { b=t; } public T get() { System.out.println(b.getClass()); return b; } }下面我们就用书柜来装小说
//以前的写法,无法编译通过,提示Incompatible types, Required Book Found Novel Bookcase<Book> bc = new Bookcase<Novel>(new Novel());