- 1,java7提供的泛型菱形语法
List<String> list = new ArrayList<String>(); Map<String, String> map = new HashMap<String, String>();为了绕开这么恶心的写法,我都习惯用google的common包了。代码如下:
List<String> list = Lists.newArrayList(); Map<String, String> map = Maps.newHashMap();在java7之后,java允许在构造器后不需要带完整的泛型信息,只要给出一对尖括号就可以,具体的java可以推断出应该是什么泛型信息,上面的代码可以做如下修改:
List<String> list = new ArrayList<>(); Map<String, String> map = new HashMap<>();上面的代码对原来的泛型并没有任何改变,只是更好的简化了泛型编程。
- 2,定义泛型接口和类
public class Test<T> { //实例属性中可以使用泛型T private T name; //定义构造器可以使用泛型T public Test() { } public Test(T name) { this.name = name; } public T getName() { return name; } public void setName(T name) { this.name = name; } public static void main(String[] args) { //初始化实例的时候构造器后面的尖括号可以省略 Test<String> test1 = new Test<>(); test1.setName("LinkinPark..."); System.out.println(test1.getName()); Test<Integer> test2 = new Test<>(); } }
注意:当创建带泛型声明的自定义类时,为该类定义构造器时,构造器还是原来的类名,不可以增加泛型申明。比如说为Test<T>类定义构造器,其构造器名依然是Test,不是Apple<T>。
- 3,从泛型类派生子类
class Test1 extends Test<T> { }
如果想从一个接口或者父类派生子类的话,我们应该为T的泛型形参传入实际的类型。正确的写法如下:
class Test1 extends Test<String> { }
值得注意的2点:
1,如上面的代码Test1类中,我们继承了Test<String>类,Test中所有使用T类型形参的地方都被替换成了String类型,Test类中原来所有的方法的形参也都变成了具体的类型了。我们在重写父类的方法的时候要特别注意这一点。
比如原来的Test类中有一个方法是:
public T getName() { }我们在重写这个方法时候应该写成
public String getName() { }
2,调用方法的时候必须为所有的数据形参传入参数值,和调用方法不同,使用类和接口的时候可以不为类型形参T传入实际的类型参数,这个时候我们就不能写上泛型T标示符了。比如下面的代码也是正确的:
class Test1 extends Test { }
如果没有为泛型T传入实际的类型参数,Java编译器会发出警告,使用了未经检查或者不安全的操作。此时系统会把类里面的泛型T当做Object来处理。这种写法实际上就是说没有用泛型,实际编码过程中要尽量绕开这种写法。就个人经验而言,每次我看到那个黄色警告的时候都会想办法消除掉,最土的做法就是加注解来抑制警告@SuppressWarnings("rawtypes")。