java基础:19.1 泛型

基本篇在上学期断断续续的看完了,上课、导师的项目、自学等等各种事情交汇在一起,学习的效率太低了。
反思一下自己,这学期开始学习进阶篇。

首先,回顾一下11章学过的内容ArrayList。Java 定义了一个泛型类ArrayList用于存储泛型类型的元素

1. 回顾ArrayList类

ArrayList是一种泛型类,具有一个泛型类型<E>,创建一个ArrayList 时,可以指定一个具体的类型来替换E。Java 提供ArrayList 类来存储不限定个数的对象。位于java.util 包中。存储在ArrayList中的元素必须是一种对象,不能使用int的基本数据类型来代替一个泛型类.

ArrayList<T> cities = new ArrayList<>() ; T可以是引用类型 例如,string,Intege,Double 或Characterr…;不能使用int 、double 或char 这样的基本类型

+ArrayList()
+add (o: E): void
+add (index: int , o: E): void
+clear(): void
+contains(o: Object): boolean
+get (index: int): E
+indexOf (o: Object): int
+isEmpty(): boolean
+lastlndex0f (o: Object): int
+remove(o: Object): boolean
+size(): int
+remove(index: int): E
+set (index: int , o: E): E

数组和ArrayList的区别
— 旦创建了一个数组,它的大小就确定下来了。可以使用方括号访问数组元素(例如:a[index]). 当创建ArrayList 后,它的大小为0。如果元索不在数组列表中,就不能使用get(index)和set(index.element)方法。向数组列表中添加、插人和删除元素是比较容易的,而向数组中添加、插人和删除元素是比较复杂的。为了实现这些操作,必须编写代码操纵这个数组。注意,可以使用;java.util.Arrays.sortUrray)方法来对一个数组排序。如果要对一个数组列表排序,使用java.util.Collections.sort(arrayList)方法。

自动拆箱
如果元素是包装类型,例如, Integer , Double 或Character ,那么可以直接将这个元素赋给一个基本类型的变量。这个过程称为自动拆箱。

ArrayList<Double> list = new ArrayList<>();
list.add(5.5);   // 5.5 is automatlcally converted to new Double(5.5)
1 i st. add (3.0);  // 3. 0 i s automati ca 11 y converted to new Ooub 1 e (3 .0)
Double doubleObject = list.get(O); // No casting is needed
double d = list.get(l); // Automatically converted to double

 

2. 泛型的概念

泛型类型<E>

方法申明 public class Name <E> {…}

方法调用 Name <Type> example1 = new Name<>();

泛型的优点:可以在编译时检测出错误。泛型类或方法允许用户指定可以和这些类或方法一起工作的对象类型。如果试图使用一个不相容的对象,编译器就会检测出这个错误。

注意1:有时候,泛型类可能会有多个参数。在这种情况下,应将所有参数一起放在尖括号中,并用逗号分隔开,比如<E1,E2, E3> 。
注意2:可以定义一个类或者接口作为泛型类或者泛型接口的子类型。例如,在Java API中,java.lang.String类被定义为实现Comparable接口,如下所示: public class String implements Comparable<String>

下文写了一个用泛型定义的栈
注意3:为了创建一个字符串堆找,可以使用new GenericStack<String>() 或new GenericStack<>() 。这可能会误导你认为GenericStack 的构造方法应该定义为 public GenericStack\<E>()这是错误的。它应该被定义为 public GenericStack()
定义泛型类

public class GenericStack <E> {
	private java.util.ArrayList<E> list = new java.util.ArrayList<>();
	
	public int getSize() {
		return list.size();
	}
	public E peek() {
		return list.get(getSize()-1);
	}	
	public void push(E o) {
		list.add(o);
	}	
	public E pop() {
		E o = list.get(getSize()-1);
		list.remove(getSize()-1);
		return o;
	}
	public boolean isEmpty() {
		return list.isEmpty();
	}
	@Override
	public String toString() {
		return "stack:" + list.toString();
	}
}

泛型类调用

public class Main {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		GenericStack <String> stack1 = new GenericStack<>();  // 上文的注意点3
		stack1.push("London1");
		stack1.push("London2");
		stack1.push("London3");
		
		GenericStack <Integer> stack2 = new GenericStack<>();
		stack2.push(1);
		stack2.push(2);
		stack2.push(3);
	}
}

定义、调用泛型方法

public class Main {
	public static void main(String[] args) {
	
		Integer[] integers = {1,2,3,4,5};
		String[] strings = {"aaa","bbb","Ccc"};
		Main.<Integer>print(integers);  //调用泛型方法
		Main.<String>print(strings);
		print(integers);   // 或者这样调用
	}
	
	public static <E> void print(E[] list) {  // 声明泛型方法,放在关键字static之后
		for(int i = 0;i < list.length; i++)
			System.out.print(list[i] + "  ");
		System.out.println();
	}
}

示例学习,用泛型方法进行排序

public class GenericSort {
	
	public static void show() {
		Integer[] intArray = {new Integer(2),new Integer(4),new Integer(3)};
		Double[] doubleArray = {new Double(2.5),new Double(6.4),new Double(3.3)};
		Character[] charArray = {new Character('a'),new Character('q'),new Character('c')};
		String[] stringArray = {"liu","lu","hhh"};
	
		sort(intArray);
		sort(doubleArray);
		sort(charArray);
		sort(stringArray);
		
		System.out.print("sorted integer objects: ");
		printList(intArray);
		System.out.print("sorted Double objects:  ");
		printList(doubleArray);
		System.out.print("sorted char objects:   ");
		printList(charArray);
		System.out.print("sorted string objects:  ");
		printList(stringArray);
		
	}
	
	public static <E extends Comparable<E>> void sort(E[] list) {  //可以对任何对象类型的数组进行排序
		E currentMin;
		int currentMinIndex;
		
		for(int i = 0; i < list.length -1 ;i++) {
			currentMin = list[i];
			currentMinIndex = i;
			for (int j = i+1 ; j < list.length; j++) {
				if(currentMin.compareTo(list[j])>0) {
					currentMin = list[j];
					currentMinIndex = j;
				}
			}
			
			if(currentMinIndex != i) {
				list[currentMinIndex] = list[i];
				list[i] = currentMin;
			}
		}
	}
	
	public static void printList(Object[] list) {
		for(int i = 0; i< list.length ; i++)
			System.out.print(list[i]+" ");
		System.out.println();
	}
}

泛型类型定义为<E extends Comparable <E>>,这具有两个含义:
首先,它指定E 是Comparable 的子类型;其次,它还指定进行比较的元素是E 类型的。
 
 

3.通配泛型

通配泛型类型有三种形式一一?? extends T 或者? super T ,其中T是泛型类型。
第一种形式 ? 称为 非受限通配 (unbounded wildcard) ,它和? extends Object 是一样的。表示任何一种对象类型。

public static void print(GenericStack <?> stack)

第二种形式 ? extends T 称为 受限通配 (bounded wildcard),表示T 或T 的一个子类型

public static double max(GenericStack <? extends Number> stack)
所以max(new GenericStack <Integer/Double>()) 都是合法的

第三种形式 ? super T 称为 下限通配 (Iower-bound wildcard) ,表示T 或T 的一个父类型

GenericStack stack1 = new GenericStack<>(); 一个字串栈
GenericStack stack2 = new GenericStack<>(); 一个对象栈
如果要调用下面的add(stack1,stack2)方法,stack2就应该申明为 <? super T>

举例,在Main.java中添加下列程序

	public static double max(GenericStack<? extends Number> stack) {  // 子类型
		double max = stack.pop().doubleValue();
		
		while(!stack.isEmpty()) {
			double value = stack.pop().doubleValue();
			if(value>max)
				max = value ;
		}
		return max;
	}
	
	public static <T> void add(GenericStack<T> stack1,
			GenericStack<? super T> stack2) {
		while(!stack1.isEmpty())
			stack2.push(stack1.pop());
	}

 

4.注意

不管实际的具体类型是什么,泛型类是被它的所有实例所共享的。假定按如下方式创建list1和list2:
ArrayList list1 = new ArrayList<>();
ArrayList list2 = new ArrayList<>();
尽管在编译时ArrayList和ArrayList是两种类型,但在运行时只有一个ArrayList类被加载到JVM中。

在静态上下文中不允许类的参数是泛型类型。由于泛型类的所有实例都有相同的运行时类,所以泛型类的静态变量和方法是被它的所有实例所共享的,因此,在静态方法、数据域或者初始化语句中,为类引用泛型类型参数是非法的。

异常类不能是泛型的

posted @ 2019-03-11 12:34  Aurora_l  阅读(313)  评论(0编辑  收藏  举报