本文主要是介绍第二十一章 泛型(generic),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
第二十一章 泛型(generic)(1)引言
泛型:是指参数化类型的能力。
例如:有这样一个类:这是一个比较简单并且是很常用的带有泛型的方法。
package com.lidd.generic;
public class GenericTestSecond {
public <T>void one(T t){
}
}
下面是几个类,分别是一般类、抽象类、接口(接口也是特殊的类)。
package com.lidd.generic;
public class A {
}
package com.lidd.generic;
public abstract class B {
}
package com.lidd.generic;
public interface C {
}
接下里是主函数:
package com.lidd.generic;
public class MainTest {
public static void main(String[] args) {
GenericTestSecond o = new GenericTestSecond();
o.one(new C(){}); //C
o.one(new A()); // A
o.one(new B(){}); // B
o.one("bbbb"); // String
o.one(1); // Integer
}
}
可以看到main方法中实例化了一个GenericTestSecond对象。方法one中传的参数类型可以是C、A、B、String、Integer等等,也就是说方法one中的泛型并不是指代某一种具体的类型
而实在具体类型的基础上又进行了一层参数化。这就是定义中所说的参数化类型的能力。
(2)泛型的优点。
在jdk 1.5之前
package java,lang;
public interface Comparable{
public int compareTo(Object o);
}
在jdk1.5开始及其以后
package java.lang;
public interface Comparable<T>{
public int compareTo(T t);
}
1、泛型使得程序更加可靠。
Comparable c = new Date();
System.out.println(c.compareTo("red"));
Comparable<Date> c = new Date();
System.out.println(c.compareTo("red"));
62 中一个时间和一个String字符串去做比较,但是在编译期不会有任何问题。但是在运行时会报错。
65 中在编译的时候就会报错,因为Comparable中使用了泛型,并且在64行指定为Date类型。
注意:
泛型类型必须是应用类型,不能用像int double或char这样的基本类型来替换泛型类型。例如下面的语句是错误的:
ArrayList<int> list = new ArrayList<int>();
必须是ArrayList<Integer> list = new ArrayList<Integer>();
2、无需类型转换。
例如:
ArrayList<String> strList = new ArrayList<String>();
strList.add("one");
strList.add("two");
String str = strList.get(0);
91 行不需要这样 String str = (String)strList.get(0);
(3) 泛型的几种常见形式。
1、泛型类(抽象类):
public class GenericStack<E>{
private java.util.ArrayList<E> list = new java.util.ArrayList<E>();
public int getSize(){
return list.size();
}
public E peek(){
return list.get(getSize()-1);
}
public void push(E e){
list.add(e);
}
public E pop(){
E o = list.get(getSize()-1);
list.remove(getSize()-1);
return o;
}
public boolean isEmpty(){
return list.isEmpty();
}
}
或者是:
public class GenericStack<E extends A>{
private java.util.ArrayList<E> list = new java.util.ArrayList<E>();
public int getSize(){
return list.size();
}
public E peek(){
return list.get(getSize()-1);
}
public void push(E e){
list.add(e);
}
public E pop(){
E o = list.get(getSize()-1);
list.remove(getSize()-1);
return o;
}
public boolean isEmpty(){
return list.isEmpty();
}
}
其中A为一个类。
2、泛型接口:
public interface Comparable<T>{
public int compareTo(T t);
}
或者是:
public interface Comparable<T extends A>{
public int compareTo(T t);
}
其中A为一个类。
3、泛型方法:
public class MyTest{
// 注意<T>在方法的返回值类型之前
public <T>void one(T t){
}
}
或者:
public class MyTest{
// 注意<T>在方法的返回值类型之前
public <T extends A>void one(T t){
}
}
其中A为一个类。
(4)通配泛型:
以95行的类做前置准备。
为啥需要通配泛型?
pulic class demo1{
public static void main(String[] args){
GenericStack<Integer> stack = new GenericStack<Integer>();
stack.add(1);
stack.add(2);
stack.add(3);
System.out.println("The max number is"+max(stack));
}
public static double max(GenericStack<Number> stack){
double max = stack.pop().doubleValue();
while(!stack.isEmpty()){
double value = stack.pop().doubleValue();
if(max < value){
max = value;
}
}
return max;
}
}
其中208会出现编译错误,虽然Integer是Number的子类,但是GenericStack<Integer> 不是GenericStack<Number>的子类.
这个时候通配泛型登场了。
上面的代码稍加改动就可以消除208的编译错误。
修改:211-221
public static double max(GenericStack<? extends Number> stack){
double max = stack.pop().doubleValue();
while(!stack.isEmpty()){
double value = stack.pop().doubleValue();
if(max < value){
max = value;
}
}
return max;
}
1、通配泛型的分类:
第一类:?(非受限通配) 相当于 ?extends Object。
例子:
pulic class demo2{
public static void main(String[] args){
GenericStack<Integer> stack = new GenericStack<Integer>();
stack.add(1);
stack.add(2);
stack.add(3);
print(stack);
}
public static double print(GenericStack<?> stack){
while(!stack.isEmpty()){
System.out.println(stack.pop()+"");
}
}
}
注意253行-259行
虽然GenericStack<?>相当于GenericStack<? extends Object>,但是不能是
public static double print(GenericStack<Object> stack){
while(!stack.isEmpty()){
System.out.println(stack.pop()+"");
}
}
否则的话250行编译不能通过。这是因为GenericStack<Integer> 不是GenericStack<Object>的子类。此处有体现的通配泛型的
必要性。
第二类:?extends T (受限通配) // 其中的T是某个泛型类型。
参考228-239行。
第三类:?super T (下限通配)// 其中的T是某个泛型类型。
public class demo3{
public static void main(String[] args){
GenericStack<String> stack1 = new GenericStack<String>();
GenericStack<Object> stack2 = new GenericStack<Object>();
stack1.add("java");
stack1.add("love");
stack2.add(1);
stack2.add(2);
add(stack1,stack2);
}
public static <T>void add(GenericSatck<T> stackTo,GenericStack<? super T> destStack){
while(!stackTo.isEmpty()){
destStack.push(stack1.pop());
}
}
}
296行如果使用<T>代替<? super T> ,那么293就会编译异常。
(5)泛型消除:
泛型是使用一种称为类型消除的方法来实现的。编译器使用泛型类型信息来编译代码,
但是随后就会消除它。因此,泛型信息在运行时是不可用的。
//===========================================读java语言程序设计进阶篇笔记====================================================
这篇关于第二十一章 泛型(generic)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!