泛型
使用泛型的主要优点是能够在编译时发现错误,而不是在运行时检验错误。
泛型类的定义:[修饰符] class 类名
泛型接口的定义:[public] interface 接口名
泛型方法的定义:[public] [static]返回值类型 方法名(T参数)
注意:不能使用泛型的类型参数T创建对象;在泛型中可以用类型参数T声明数组,但不能用类型参数T创建数组;不能在静态环境中使用泛型类的类型参数T;异常类不能是泛型的。
泛型类及应用
泛型在实例化时,可根据不同需求给出类型参数T的具体类型。在实例化泛型类时,实际类型必须是引用类型,即必须是类类型,不能用基本类型来替换类型参数T。
调用泛型类的方法传递或返回数据类型时可以不用类型转换,直接用T作为类型代替参数类型或返回值类型。
public class Test<T> {//泛型类
private T obj;//泛型类的成员变量
public T getObj() {//泛型类的方法
return obj;
}
public void setObj(T obj) {//泛型类的方法
this.obj = obj;
}
public static void main(String[] args) {
Test<String> name = new Test<String>(); //创建<String>型对象
Test<Integer> age = new Test<Integer>();//创建<Integer>型对象
name.setObj("张三");
age.setObj(20);
String newName= name.getObj();
int newAge= age.getObj();
System.out.println("姓名:"+newName);
System.out.println("年龄:"+newAge);
}
}
限制泛型类的可用类型
类型参数T必须是anyClass类或它的子类或是实现了anyClass接口的类。
public class Test {
public static void main(String[] args) {
Type<Integer>num=new<Integer>Type(5);//创建泛型对象
System.out.println("给出的参数:"+num.getObj());
/*错误案例
Type<String>err=new<String>Type(5);
System.out.println("给出的参数:"+err.getObj);
错误原因:实际参数String不是Number及其子类
*/
}
}
class Type<T extends Number>{//类型参数T必须是Number类或它的子类
T obj;//定义泛型类的成员变量
public Type(T obj){
this.obj=obj;
}
public T getObj(){//定义泛型类的方法
return obj;
}
}
泛型数组的应用
public class Type<T>{
private T[] arr;//定义泛型数组
public void setT(T[] arr){//方法的参数接收类型参数T类型的数组
this.arr=arr;
}
public T[] getT() {//方法返回值为类型参数T类型的数组
return arr;
}
public static void main(String[] args) {
Type<String> a=new Type<String>();//创建泛型对象
String[] arr={"cat","dog","pig"};
a.setT(arr);//用数组调用setT()方法
for (int i = 0; i < arr.length ; i++) {
System.out.print(a.getT()[i]+" ");//调用getT()方法输出数组的内容
}
}
}
容器类
容器接口Collection
Set(集合接口)和List(列表接口)都继承了Collection接口。
List接口中包含的是元素有序,可重复的集合;Set接口中包含的是元素无序,不可重复的集合。
实现列表接口List的类主要有两个:LinkedList(链表类)和ArrayList(数组列表类)。
LinkedList链表类:向链表中任意位置插入或删除元素是不需要移动其他元素的。
ArrayList数组列表类:向其中添加元素时,容量会自动增大,但不能自动缩小,但可以用trimToSize方法将数组的容量减小到数组列表的大小。
利用LinkedList类构造一个先进后出的堆栈。
import java.util.LinkedList;
import java.util.Scanner;
class StringStack{
private LinkedList<String> id=new LinkedList<String>();//创建LinkedList对象
public void push(String name){//将输入的数据入栈
id.push(name);//将name添加到链表的表头
}
public String pop(){//获取并删除栈顶数据
return id.removeFirst();//获取并移除堆栈中第一个元素
}
public boolean isEmpty(){//判断堆栈是否为空
return id.isEmpty();
}
}
public class Test{
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
StringStack stack=new StringStack();
System.out.println("请输入数据 输入(quit)代表结束");
while(true){
String input=sc.next();
if(input.equals("quit"))
break;
stack.push(input);//入栈
}
System.out.println("先进后出的顺序:");
while (!stack.isEmpty())
System.out.print(stack.pop()+" ");//出栈
}
}
最先放入栈中的元素在栈底(Bottom),最后放入栈中的元素在栈顶(Top),而删除元素时最后放入的元素先删除。
创建数组对象并添加元素
import java.util.*;
public class Teat{
public static void main(String[] args) {
ArrayList<Integer> a1=new ArrayList<Integer>();
for (int i = 1; i <5 ; i++) {
a1.add(i);//向数组中添加元素
}
System.out.println("数组的原始数据:"+a1);
ListIterator<Integer> listIter=a1.listIterator();
listIter.add(0);//在序号为0的元素前添加一个元素0
System.out.println("添加数据后数组列表"+a1);
}
}
集合接口Set
HashSet(哈希集合类)和TreeSet(树集合类)都继承了Set接口。HashSet在元素的储存位置和元素的值之间创立一个对应关系,使每个元素与唯一储存位置对应。在比较两个加入哈希集合的元素是否相同时,先比较HashCode()方法的返回值是否相同,若相同则再使用equals方法比较二者的内存地址是否相同,若也相同,则二者视为相同元素。
TreeSet与HashSet相似,但TreeSet额外添加一个步骤,使集合中的元素有序。
映射接口Map
HashMap(哈希映射)和TreeMap(树映射)是基于Map接口的实现类。
HashMap通过哈希码对内部映射关系快速查找,因此添加删除映射关系效率极高,且允许使用null值和null键。
TreeMap中的映射关系根据键对象按照一定的顺序排列,因此不允许键对象为null。