泛型是JDK5.0之后推出的新个性,泛型这种语法机制,只在程序编译阶段起作用,只是给编译器参考的,运行阶段泛型是不起作用的。
应用泛型的益处
1) 汇合中存储的元素类型对立了。2)汇合中取出来的元素类型是泛型指定的类型,不须要进行大量的“向下转型”。
泛型的毛病
1)汇合存储的元素短少多样性。 大多数业务中,汇合中的元素类型还是对立的,所以这种性能还是被大家认可的。
案例
首先创立一个JAVA我的项目,在我的项目中创立一个类,类外面写上主办法,而后在这个类中再创立三个类,其中一个类是剩下两个类的父类。每个类里都写上一个办法,而后子类重写父类的eat办法。
主办法中创立一个List汇合先不指定泛型,用list.add办法将咱们创立的类的对象存入到汇合中,因为是三个不同的类所以存入到汇合中的元素类型也是不一样的,接下来咱们用调用list的迭代器办法来遍历汇合。
能够看到it.next办法返回的对象是一个Object类,而这个类中并没有提供eat办法。所以咱们调用不了编译器报错。要想解决这个办法咱们能够应用向下转型(强制转换)。
这样把it.next返回的类型强制转换成Animals类就能够调用外面的eat办法了,能够看到控制台输入了三个eat的办法,别离是三个不同类的,因为子类继承了父类而后重写了办法(不重写的话默认是父类的eat办法体内容),咱们之前通过list.add增加了三个类的对象再汇合中所以遍历输入了三个类的eat办法。
如果要应用泛型咱们须要再汇合上用<类型> 尖括号外面写上你要指定的汇合中能存储的元素类型。
迭代器上也要写上你要指定遍历的元素类型。
这样你的List汇合中能存储的元素类型就是你用泛型指定的类型,
因为迭代器上用了泛型所以遍历的也是汇合外面这个泛型指定的类型,it.next中返回的类型就是你指定的类型,咱们之所以指定Animals而不是指定它的子类是因为如果你指定其中一个子类那么剩下的Animals中的子类就不能存储到元素中编译器会报错因为不是同个类型。
应用了泛型后迭代器循环中就不须要把Object类强制转换成Animals了,因为it.next默认返回的类型就是你指定的类型。
如果要输入子类的特有办法咱们还是须要向下转型将Animals转换成它的子类,无论是不是用泛型,这样才不会编译报错,因为是特有办法,父类中并没有写这个办法,这个办法是子类特有的所以,不能应用父类对象调用子类办法,只能向下转型。
在JDK8之后引入了主动类型推断机制(也称为钻石表达式)
也就是ArrayList前面的尖括号里能够不写类型了,它会主动推断,只有在JDK8之后才容许。因为这两个尖括号看起来像钻石所以也叫钻石表达式。
自定义泛型
自定义泛型的应用办法,创立一个类。类名前面写上泛型,这个泛型里的内容是个标识符能够轻易写,个别写E(Element)和T(Type)。而后写上泛型后,类里的办法如果有参数就必须是这个类上的泛型的标识符,也能够没有参数,如果有返回类型的话也必须是这个泛型的标识符,也能够是void。
能够看到当咱们在办法里new对象时如果加上泛型那么这个泛型就会传到咱们在类上写的泛型,就会传到办法的类型参数或者返回类型上,这样就是自定义泛型。在创立GenericaTest对象时在写上泛型String这样传到类中,就会把E改成String,办法里的参数E o 也就变成String o 办法返回值上的 public E run()就变成public String run()。在调用这两个办法,add()中须要传入一个String 类型参数否则会报错,而run()办法返回值则能够是String或者Object因为Object是所有没有被动继承类的超级父类。