1、泛型具有参数化类型的能力。可以定义使用泛型的类和方法、编译器会用具体类型替代泛型
2、泛型的优势在于能够在编译时发现错误而不是在运行时检测错误
3、不使用类型参数的泛型类称为原生类型,例如 ArrayList,
4、通配泛型的三种形式:
? 等价于? extends Object
? super T 表示T或T的父类型
? extends T 类型T或T的子类型
5、泛型的使用是通过“类型擦除”来实现的。一旦编译器确定泛型是安全使用的,就将他转换为泛型的原生类型:
< F > -----------> < Object >
< E extends xxx> -----------> < xxx >
6、不能用泛型类型创建实例 例如 new E()
7、不能使用泛型类型参数来创建数组 例如 new E [10]
8、异常类中不能使用泛型类型参数
package cn.ALAN_CF.studyf013;
import java.util.ArrayList;
/**
* @author 15328
* 泛型类型必须是引用型的,不能用基本数据类型代替泛型类型
* 为一个类定义泛型:泛型类型放在类名之后,例如:GenericStack<E>
* 为一个方法定义泛型:泛型类型放在方法返回类型之前。例如:<E> void max(E o1, E o2)
*/
public class Genericfir {
public static void main(String[] args) {
//泛型初探
first();
//定义泛型类与泛型接口
GenericStack<String> stack1 = new GenericStack<>();
stack1.push("London");
stack1.push("Paris");
stack1.push("Berlin");
System.out.println("the stack1 is : " + stack1);
GenericStack<Integer> stack2 = new GenericStack<>();
stack2.push(1);
stack2.push(2);
stack2.push(3);
System.out.println("the stack2 is : " + stack2);
//定义泛型方法
Integer[] integers = {1, 2, 3, 4, 5, 6};
String[] strings = {"London", "Paris", "New York", "Austin"};
print(integers);
print(strings);
Genericfir.<Integer>print(integers);
Genericfir.<String>print(strings);
//原生类型与向后兼容
//原生类型不安全,减少使用
GenericStack stack = new GenericStack();
GenericStack<Object> stack3 = new GenericStack<>();
//没有指定具体类型的泛型类和泛型接口被称为原生类型,前面两个等价
//通配泛型
GenericStack<Integer> intStack = new GenericStack<>();
intStack.push(35);
intStack.push(28);
intStack.push(25);
intStack.push(99);
intStack.push(-100);
System.out.println("the max number is " + max(intStack));
//
GenericStack<String> stringStack = new GenericStack<>();
GenericStack<Object> objectStack = new GenericStack<>();
stringStack.push("dddd");
stringStack.push("aaaa");
objectStack.push("java");
objectStack.push(2);
System.out.println("the string" + stringStack.toString());
System.out.println("the object" + objectStack.toString());
add(stringStack,objectStack);
System.out.println(objectStack);
System.out.println(stringStack);
stringStack.push("again");
stringStack.push("java16hhhhh");
System.out.println(stringStack);
add2(stringStack,objectStack);
System.out.println(objectStack);
}
public static int max(GenericStack<? extends Number> intStack) {
//<? extends Number> 表示Number或Number子类型的通配类型
int Max = 0;
if(!intStack.isEmpty()) {
Max =intStack.peek().intValue();
}
while(!intStack.isEmpty()) {
if(intStack.peek().intValue() > Max){
Max = intStack.peek().intValue();
}
intStack.pop();
}
return Max;
}
public static void add(GenericStack<String> stringStack,GenericStack<? super String> objectStack) {
//<? super T>类型T或类型T的父类型
while(!stringStack.isEmpty()){
objectStack.push(stringStack.pop());
}
}
public static void add2(GenericStack<? extends Object> stringStack,GenericStack<Object> objectStack) {
//与add(...)等价
while(!stringStack.isEmpty()){
objectStack.push(stringStack.pop());
}
}
public static void first(){
//泛型初探
System.out.println("String 类型的ArrayList ");
ArrayList<String> list1 = new ArrayList<>();
list1.add("Red");
list1.add("White");
String s = list1.get(1);
System.out.println("String s = list1.get(1); s 为:" + s);
}
public static <E> void print(E[] list){
/*
定义泛型方法
<E>保证了后面(E[] list)的E类型的存在
可以将泛型指定为另一种类型的子类型: <E extends GeometricObject>,
其中E被指定为类型GeometricObject的泛型子类型,必须传递两个GeometricObject的实例使用
非受限泛型类型<E>等同于<E extends Object>
*/
for(E e : list) {
System.out.print(e + " ");
}
System.out.println();
/* 另一种写法,不如前面的简便
for(int i = 0; i < list.length; i++){
System.out.print(list[i] + " ");
}
System.out.println();
*/
}
}
class GenericStack<E>{
//定义泛型类与泛型接口
/**将元素类型通用化为泛型,创建一个栈类*/
private final ArrayList<E> list = new ArrayList<>();
/**注意:private 私有list
* 此时,list为ArrayList的对象引用,且不需要再指向其他ArrayList对象,所以可以声明为final类型
* final表示该对象引用所指向的内存起始地址锁死了,并不影响创建单一一个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();
}
}