Java进阶之泛型

泛型的优势

  1. 泛型类型能够提升可靠性和可读性
  2. 泛型能够参数化类型
  3. 泛型可让咱们在编译时而不是在运行时检测出错误

泛型类或方法容许用户指定能够和这些类或方法一块儿工做的对象类型(相容的对象)
泛型类ArrayList、泛型接口Comparable
从JDK1.5开始,Java容许定义泛型类、泛型接口、泛型方法数组

泛型实例化

Java进阶之泛型
泛型就是限制对象的数据类型ide

泛型的正确使用

举个栗子吧

建立一个存储字符串的线性表(ArrayList)测试

ArrayList<String> list = new ArrayList<>();

如今就只能向该线性表中添加字符串code

list.add("a");

若是试图向其中添加非字符串类型,就会产生编译错误对象

list.add(new Person("张三",23));

当没有使用泛型时,编译经过,运行也经过,便可以添加任何元素,但这样作在遍历元素进行相关操做时会产生隐藏的bug。blog

 
泛型类型必须是引用数据类型,不能使用基本数据类型。接口

错误示范

ArrayList<int> list = new ArrayList<>();

正确示范

ArrayList<Integer> list = new ArrayList<>();
list.add(5);      //自动装箱

 
使用泛型对数据类型进行限制后,无须类型转换就能够从一个线性表中获取一个值,由于编译器已经知道了这个元素的类型。ci

使用泛型前

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

定义泛型类和接口

能够为类或者接口定义泛型。当使用容器类来建立对象,或者使用容器类或接口来声明引用变量时,必须指定具体的类型。rem

利用ArrayList模拟堆栈结构,使用泛型对元素类型进行限制

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)

相关文章
相关标签/搜索