泛型类或方法允许用户指定可以和这些类或方法一起工作的对象类型(相容的对象)
泛型类ArrayList、泛型接口Comparable
从JDK1.5开始,Java允许定义泛型类、泛型接口、泛型方法
泛型就是限制对象的数据类型
创建一个存储字符串的线性表(ArrayList)
ArrayList<String> list = new ArrayList<>();
现在就只能向该线性表中添加字符串
list.add("a");
如果试图向其中添加非字符串类型,就会产生编译错误
list.add(new Person("张三",23));
当没有使用泛型时,编译通过,运行也通过,即可以添加任何元素,但这样做在遍历元素进行相关操作时会产生隐藏的bug。
泛型类型必须是引用数据类型,不能使用基本数据类型。
ArrayList<int> list = new ArrayList<>();
ArrayList<Integer> list = new ArrayList<>();
list.add(5); //自动装箱
使用泛型对数据类型进行限制后,无须类型转换就可以从一个线性表中获取一个值,因为编译器已经知道了这个元素的类型。
ArrayList list = new ArrayList();
list.add("Jone"); //自动提升为Object类型
list.add("Smith");
String s = (String)(list.get(0));//将Object类型转为String类型
ArrayList<Double> list = new ArrayList<>();
list.add(5.5); //5.5 is automatically converted to new Double(5.5)
list.add(3.0); //3.0 is automatically converted to new Double(3.0)
Double doubleObject = list.get(0); //No casting is needing
double d = list.get(1); //Automatically converted to double
可以为类或者接口定义泛型。当使用容器类来创建对象,或者使用容器类或接口来声明引用变量时,必须指定具体的类型。
public class Stack<E>{
//构造方法
public Stack(){}
//创建数组列表,存储元素的数据类型为E,需导包alt+shift+O
private ArrayList<E> list = new ArrayList<>();
//返回栈中的元素数目
public int getSize(){
return list.size();
}
//返回栈顶元素
public E peek(){
return list.get(getSize() - 1);
}
//返回并移除栈顶元素
public E pop(){
E o = list.get(getSize() - 1);
list.remove(getSize() - 1);
return o;
}
//添加一个新元素到栈顶
public void push(E o){
list.add(o);
}
//如果栈为空,就返回true
public boolean isEmpty(){
return list.isEmpty();
}
@Override
public String toString(){
return "stack : " + list.toString();
}
}
若使用LinkedList模拟堆栈结构,可以用getLast()、removeLast()、addLast()方法
上面自定义类的构造方法不是public Stack<E>(){},而是public Stack(){}
泛型可能会有多个参数,应将所有参数一起放在尖括号中,并用逗号分隔开,比如<E1,E2,E3>
可以定义一个类或接口作为泛型类或者泛型接口的子类型
例如
public final class String
extends Object
implements Serializable, Comparable<String>, CharSequence
可以为静态方法定义泛型类型
public clas GenericMethodDemo{
public static void main(String[] args){
Integer[] integers = {1,2,3,4,5};
String[] strings = {"London","Paris","New York","Austin"};
GenericMethodDemo.<Integer>print(integers);
GenericMethodDemo.<String>print(strings);
}
public static <E> void print(E[] list){
for(int i = 0;i<list.length;i++){
System.out.print(list[i]+" ");
System.out.println();
}
}
为了声明泛型方法,将泛型类型<E>置于方法声明中关键字static之后
public static <E> void print(E[] list)
为了调用泛型方法,需要将实际类型放在尖括号内作为方法名的前缀。例如,
GenericMethodDemo.<Integer>print(integers);
GenericMethodDemo.<String>print(strings);
简单调用
print(integers);
print(strings);
可以将泛型指定为另外一种类型的子类型,这样的泛型类型称为受限的。例如下面所示的代码用以测试两个几何对象是否具有相同的面积。受限的泛型类型将E指定为GeometricObject的泛型子类型。此时必须传递两个GeomericObject的实例来调用equalArea
public class BoundedTypeDemo{
public static void main(String[] args){
Rectangle rectangle = new Rectangle(2,2);
Circle circle = new Circle(2);
System.out.println("Same area?" + equalArea(rectangle,circle));
}
public static <E extends GeometricObject> boolean equalArea(
E object1,E object2){
return object1.getArea()==object2.getArea();
}
}
非受限泛型类型<E>等同于<E extends Object>
为了定义一个类为泛型类型,需要将泛型类型放在类名之后,例如,GenericStack
为了定义一个方法为泛型类型,要将泛型类型放在方法返回类型之前,例如,void max(E o1,E o2)
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。