1、java语言支持的类型参数
实体类型:传入一个类或其他引用类型名称作为类型参数。例如,List,Animal作为参数传给E。
实体参数化类型:传入一个实体参数化类型名称作为类型参数。例如,Set<List>,List作为参数传给E。
数组类型:传入一个数组作为类型参数。例如,Map<String, String[]>,String传入给K,String[]传入给V。
类型参数:直接把类型参数传入作为类型参数。例如,在类Container {Set elements;}中,E就作为参数传给了E。
通配符:传入问号符作为类型参数。例如,Class<?>,?号作为参数类型传给T
2、java泛型
泛型(Generic type 或者 generics)是对java语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。可以把类型参数看作是使用参数化类型时,指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样,可以在集合框架(Collection framework)中看到泛型的动机。例如,Map 类允许您向一个 Map 添加任意类的对象,即使最常见的情况是在给定映射(map)中保存某个特定类型(eg: String、integer)的对象。
3、泛型的好处
java语言中引入泛型是一个较大的功能增强。不仅语言、类型系统和编译器有了较大的变化,以支持泛型,而且类库也进行了大翻修,所以许多重要的类,比如集合框架,都已经成为泛型化的了,在定义泛型类或声明泛型类的变量时,使用尖括号来指定形式类型参数。形式类型参数与实际类型参数之间的关系类似于形式方法参数与实际方法参数之间的关系,只是类型参数表示类型,而不是表示值。
4、泛型方法通过在类的定义中添加一个形式类型参数列表,可以将类泛型化。方法也可以被泛型化,不管它们定义在其中的类是不是泛型化的,泛型类可以在多个方法签名间实施类型约束,eg:在 List<T> 中,类型参数 T 出现在 get()、add()、contains() 等方法的签名中。
5、泛型的简单实例
eg1:Box实例
package cn.generic.learn;
public class Box<T> {
private T[] elements;
private int index;
public Box(int size) {
elements = (T[]) new Object[size];
index = 0;
}
public void add(T element) {
elements[index++] = element;
}
public T get(int index) {
return elements[index];
}
public int size() {
return index;
}
}
TestBox.java测试类
package cn.generic.learn;
public class TestBox {
public static void main(String[] args) {
Box<String> box = new Box<String>(4);
box.add("square");
box.add("circle");
box.add("trial");
box.add("ren");
for (int i = 0; i < box.size(); i++) {
System.out.println(box.get(i));
}
}
}
eg2:Employee实例
package cn.generic.learn;
import java.math.BigDecimal;
public class Employee {
private BigDecimal yearSalary;
private String department;
public Employee(BigDecimal yearSalary, String department) {
this.yearSalary = yearSalary;
this.department = department;
}
public BigDecimal getYearSalary() {
return yearSalary;
}
public void setYearSalary(BigDecimal yearSalary) {
this.yearSalary = yearSalary;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
@Override
public String toString() {
return "Employee [yearSalary=" + yearSalary + ", department="
+ department + "]";
}
}
Accountant.javapackage cn.generic.learn;
import java.math.BigDecimal;
public class Accountant extends Employee implements Comparable<Accountant> {
public Accountant(BigDecimal yearSalary, String department) {
super(yearSalary, department);
}
@Override
public int compareTo(Accountant accountant) {
return getYearSalary().compareTo(accountant.getYearSalary());
}
}
SortedEmployees.java
package cn.generic.learn;
import java.util.Arrays;
public class SortedEmployees<T extends Employee & Comparable<T>> {
private T[] employees;
private int index;
public SortedEmployees(int size) {
employees = (T[]) new Employee[size];
int indez = 0;
}
public void add(T emp) {
employees[index++] = emp;
Arrays.sort(employees, 0, index);
}
public T get(int index) {
return employees[index];
}
public int size() {
return index;
}
}
Employee测试类
package cn.generic.learn;
import java.math.BigDecimal;
public class TestEmployee {
public static void main(String[] args) {
SortedEmployees<Accountant> sa = new SortedEmployees<Accountant>(5);
sa.add(new Accountant(new BigDecimal("20.00"), "software department"));
sa.add(new Accountant(new BigDecimal("10.00"), "Account department"));
sa.add(new Accountant(new BigDecimal("15.00"), "server department"));
sa.add(new Accountant(new BigDecimal("44.00"), "leader department"));
sa.add(new Accountant(new BigDecimal("18.00"), "sale department"));
for (int i = 0; i < sa.size(); i++) {
System.out.println(sa.get(i));
}
}
}
实例二中:
Employee类抽象出了年薪的雇员概念,Accountant
是它的子类,并且实现Comparable<Accountant>
表明Accountants
可以根据自然顺序排序,在这个例子中是通过年薪。
java.lang.Comparable
接口被定义为接收一个类型参数T的泛型类型。这个类提供了一个int compareTo(T o)
方法用于比较当前对象和传入参数(T类型),当当前对象小于,等于,大于指定对象时分别返回负整数,0,和正整数。
SortedEmployees
类在内部数组中允许你保存继承Employee且实现Comparable
的实例。这个数组会在Employee
子对象被添加后根据年薪进行顺序排序(通过java.util.Arrays
的void sort(Object[] a, int fromIndex, int toIndex)
类方法)