Java 泛型类型
Java教程 - 什么是Java中的泛型类型
术语泛型意味着参数化类型。使用泛型,可以创建与不同类型的数据一起使用的单个类。在参数化类型上操作的类,接口或方法称为通用。
语法
以下是声明通用类的语法:
class className<type-param-list> {}
下面是声明对一个泛型类的引用的语法:
例子
简单泛型示例
// T is a type parameter that will be replaced by a real type
// when an object of type Gen is created.
class Gen<T> {
T ob; // declare an object of type T
Gen(T o) {
ob = o;
}
// Return ob.
T getob() {
return ob;
}
// Show type of T.
void showType() {
System.out.println("Type of T is " + ob.getClass().getName());
}
}
public class Main {
public static void main(String args[]) {
Gen<Integer> iOb = new Gen<Integer>(88);
iOb.showType();
int v = iOb.getob();
System.out.println("value: " + v);
Gen<String> strOb = new Gen<String>("Generics Test");
strOb.showType();
String str = strOb.getob();
System.out.println("value: " + str);
}
}
T
是类型参数的名称。 T
用于声明一个对象。泛型只与对象一起工作通用类型根据其类型参数而有所不同。
上面的代码生成以下结果。
例2
您可以在泛型类型中声明多个类型参数
// A simple generic class with two type parameters: T and V.
class TwoGen<T, V> {
T ob1;
V ob2;
TwoGen(T o1, V o2) {
ob1 = o1;
ob2 = o2;
}
void showTypes() {
System.out.println("Type of T is " + ob1.getClass().getName());
System.out.println("Type of V is " + ob2.getClass().getName());
}
T getob1() {
return ob1;
}
V getob2() {
return ob2;
}
}
public class Main {
public static void main(String args[]) {
TwoGen<Integer, String> tgObj = new TwoGen<Integer, String>(88, "Generics");
tgObj.showTypes();
int v = tgObj.getob1();
System.out.println("value: " + v);
String str = tgObj.getob2();
System.out.println("value: " + str);
}
}
上面的代码生成以下结果。
例3
以下代码声明并使用队列<E> 通用类型。
class Queue<E> {
private E[] elements;
private int head=0, tail=0;
Queue(int size) {
elements = (E[]) new Object[size];
}
void insert(E element) throws QueueFullException {
if (isFull())
throw new QueueFullException();
elements[tail] = element;
tail = (tail + 1) % elements.length;
}
E remove() throws QueueEmptyException {
if (isEmpty()){
throw new QueueEmptyException();
}
E element = elements[head];
head = (head + 1) % elements.length;
return element;
}
boolean isEmpty() {
return head == tail;
}
boolean isFull() {
return (tail + 1) % elements.length == head;
}
}
class QueueEmptyException extends Exception {
}
class QueueFullException extends Exception {
}
public class Main{
public static void main(String[] args)
throws QueueFullException, QueueEmptyException {
Queue<String> queue = new Queue<String>(6);
System.out.println("Empty: " + queue.isEmpty());
System.out.println("Full: " + queue.isFull());
queue.insert("A");
queue.insert("B");
queue.insert("C");
queue.insert("D");
queue.insert("E");
System.out.println("Empty: " + queue.isEmpty());
System.out.println("Full: " + queue.isFull());
System.out.println("Removing " + queue.remove());
System.out.println("Empty: " + queue.isEmpty());
System.out.println("Full: " + queue.isFull());
System.out.println("Adding F");
queue.insert("F");
while (!queue.isEmpty()){
System.out.println("Removing " + queue.remove());
}
System.out.println("Empty: " + queue.isEmpty());
System.out.println("Full: " + queue.isFull());
}
}
输出:
处理旧代码
为了处理向泛型的转换,Java允许使用没有任何类的通用类类型参数。
下面是一个显示原始类型的示例:
class MyClass<T> {
T ob;
MyClass(T o) {
ob = o;
}
T getob() {
return ob;
}
}
public class Main {
public static void main(String args[]) {
MyClass raw = new MyClass(new Double(98.6));
double d = (Double) raw.getob();
System.out.println("value: " + d);
}
}
输出:
Java 泛型方法
Java教程 - 如何在Java中创建泛型方法
可以创建一个包含在非泛型类中的通用方法。
public class Main {
static <T, V extends T> boolean isIn(T x, V[] y) {
for (int i = 0; i < y.length; i++) {
if (x.equals(y[i])) {
return true;
}
}
return false;
}
public static void main(String args[]) {
Integer nums[] = { 1, 2, 3, 4, 5 };
if (isIn(2, nums)){
System.out.println("2 is in nums");
}
String strs[] = { "one", "two", "three", "four", "five" };
if (isIn("two", strs)){
System.out.println("two is in strs");
}
}
}
上面的代码生成以下结果。
例子
下面的代码声明一个 copyList()
通用方法。
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> ls = new ArrayList<String>();
ls.add("A");
ls.add("B");
ls.add("C");
List<String> lsCopy = new ArrayList<String>();
copyList(ls, lsCopy);
List<Integer> lc = new ArrayList<Integer>();
lc.add(0);
lc.add(5);
List<Integer> lcCopy = new ArrayList<Integer>();
copyList(lc, lcCopy);
}
static <T> void copyList(List<T> src, List<T> dest) {
for (int i = 0; i < src.size(); i++)
dest.add(src.get(i));
}
}
Java通用构造函数
构造函数可以是通用的,即使它们的类不是。例如,考虑以下短程序:
class MyClass {
private double val;
<T extends Number> MyClass(T arg) {
val = arg.doubleValue();
}
void showval() {
System.out.println("val: " + val);
}
}
public class Main {
public static void main(String args[]) {
MyClass test = new MyClass(100);
MyClass test2 = new MyClass(123.5F);
test.showval();
test2.showval();
}
}
上面的代码生成以下结果。
Java 泛型接口
Java教程 - 如何使用Java泛型接口
在Java中,我们创建泛型接口。
语法
这是一个泛型接口的泛型语法:
interface interface-name<type-param-list> { // ...
type-param-list是逗号分隔的类型参数列表。当实现泛型接口时,必须指定类型参数,如下所示:
class class-name<type-param-list>
implements interface-name<type-arg-list> {
注意
一般来说,如果一个类实现了一个泛型接口,那么该类也必须是泛型的。如果一个类实现了一个特定类型的泛型接口,如下所示:
class MyClass implements MinMax<Integer> { // OK
那么实现类不需要是泛型的。
泛型接口类似泛型类。
例子
interface MinMax<T extends Comparable<T>> {
T max();
}
class MyClass<T extends Comparable<T>> implements MinMax<T> {
T[] vals;
MyClass(T[] o) {
vals = o;
}
public T max() {
T v = vals[0];
for (int i = 1; i < vals.length; i++) {
if (vals[i].compareTo(v) > 0) {
v = vals[i];
}
}
return v;
}
}
public class Main {
public static void main(String args[]) {
Integer inums[] = { 3, 6, 2, 8, 6 };
Character chs[] = { "b", "r", "p", "w" };
MyClass<Integer> a = new MyClass<Integer>(inums);
MyClass<Character> b = new MyClass<Character>(chs);
System.out.println(a.max());
System.out.println(b.max());
}
}
上面的代码生成以下结果。
Java 泛型类扩展
Java教程 - 如何扩展Java泛型类
泛型类可以充当超类或者作为子类。在泛型层次结构中,需要任何类型参数由泛型超类必须由所有子类向上传递到层次结构。
例子
使用泛型超类
class MyClass<T> {
T ob;
MyClass(T o) {
ob = o;
}
T getob() {
return ob;
}
}
class MySubclass<T, V> extends MyClass<T> {
V ob2;
MySubclass(T o, V o2) {
super(o);
ob2 = o2;
}
V getob2() {
return ob2;
}
}
public class Main {
public static void main(String args[]) {
MySubclass<String, Integer> x = new MySubclass<String, Integer>("Value is: ", 99);
System.out.print(x.getob());
System.out.println(x.getob2());
}
}
上面的代码生成以下结果。
例2
非类属类是类属子类的超类是完全可以接受的。
class MyClass {
int num;
MyClass(int i) {
num = i;
}
int getnum() {
return num;
}
}
class MySubclass<T> extends MyClass {
T ob;
MySubclass(T o, int i) {
super(i);
ob = o;
}
T getob() {
return ob;
}
}
public class Main {
public static void main(String args[]) {
MySubclass<String> w = new MySubclass<String>("Hello", 4);
System.out.print(w.getob() + " ");
System.out.println(w.getnum());
}
}
上面的代码生成以下结果。
例3
instanceof运算符可以应用于泛型类的对象。
class Gen<T> {
T ob;
Gen(T o) {
ob = o;
}
T getob() {
return ob;
}
}
class Gen2<T> extends Gen<T> {
Gen2(T o) {
super(o);
}
}
public class Main {
public static void main(String args[]) {
Gen<Integer> iOb = new Gen<Integer>(88);
Gen2<Integer> iOb2 = new Gen2<Integer>(99);
Gen2<String> strOb2 = new Gen2<String>("Generics Test");
System.out.println("iOb2 is instance of Gen2"+(iOb2 instanceof Gen2<?>));
System.out.println("iOb2 is instance of Gen"+(iOb2 instanceof Gen<?>));
System.out.println("strOb2 is instance of Gen2"+(strOb2 instanceof Gen2<?>));
System.out.println("strOb2 is instance of Gen"+(strOb2 instanceof Gen<?>));
System.out.println("iOb is instance of Gen2"+(iOb instanceof Gen2<?>));
System.out.println("iOb is instance of Gen"+(iOb instanceof Gen<?>));
}
}
输出:
例4
泛型类中的方法可以像任何其他方法一样重写。
class Gen<T> {
T obj;
Gen(T o) {
obj = o;
}
T getob() {
System.out.print("Gen"s getob(): ");
return obj;
}
}
class Gen2<T> extends Gen<T> {
Gen2(T o) {
super(o);
}
T getob() {
System.out.print("Gen2"s getob(): ");
return obj;
}
}
public class Main {
public static void main(String args[]) {
Gen<Integer> iOb = new Gen<Integer>(88);
Gen2<String> strOb2 = new Gen2<String>("Generics Test");
System.out.println(iOb.getob());
System.out.println(strOb2.getob());
}
}
上面的代码生成以下结果。
Java泛型类型转换
你可以将一个泛型类的一个实例转换成另一个只有两个是兼容的,它们的类型参数是相同的。
例如,假设以下程序,此强制转换是合法的:
class Gen<T> {
T ob;
Gen(T o) {
ob = o;
}
T getob() {
return ob;
}
}
class Gen2<T> extends Gen<T> {
Gen2(T o) {
super(o);
}
}
public class Main {
public static void main(String args[]) {
Gen<Integer> iOb = new Gen<Integer>(88);
Gen2<Integer> iOb2 = new Gen2<Integer>(99);
Gen2<String> strOb2 = new Gen2<String>("Generics Test");
iOb = (Gen<Integer>) iOb2;
}
}
因为iOb2是Gen< Integer>的实例。 但是,这个演员:
class Gen<T> {
T ob;
Gen(T o) {
ob = o;
}
T getob() {
return ob;
}
}
class Gen2<T> extends Gen<T> {
Gen2(T o) {
super(o);
}
}
public class Main {
public static void main(String args[]) {
Gen<Integer> iOb = new Gen<Integer>(88);
Gen2<Integer> iOb2 = new Gen2<Integer>(99);
Gen2<String> strOb2 = new Gen2<String>("Generics Test");
//iOb = (Gen<Long>) iOb2;//wrong
}
}
是不合法的,因为iOb2不是Gen<Long>的实例。
Java 泛型限制
Java教程 - 什么是Java泛型限制
类型参数不能实例化
不能创建类型参数的实例。例如,考虑这个类:
// Can"t create an instance of T.
class Gen<T> {
T ob;
Gen() {
ob = new T(); // Illegal!!!
}
}
静态成员的限制
没有静态成员可以使用由封装类声明的类型参数。例如,此类的所有静态成员都是非法的:
class Wrong<T> {
// Wrong, no static variables of type T.
static T ob;
// Wrong, no static method can use T.
static T getob() {
return ob;
}
// Wrong, no static method can access object of type T.
static void showob() {
System.out.println(ob);
}
}
您可以使用自己的类型参数声明静态泛型方法。
泛型数组限制
您不能实例化基本类型是类型参数的数组。您不能创建类型特定的泛型引用的数组。
以下短程序显示了两种情况:
class MyClass<T extends Number> {
T ob;
T vals[];
MyClass(T o, T[] nums) {
ob = o;
vals = nums;
}
}
public class Main {
public static void main(String args[]) {
Integer n[] = { 1 };
MyClass<Integer> iOb = new MyClass<Integer>(50, n);
// Can"t create an array of type-specific generic references.
// Gen<Integer> gens[] = new Gen<Integer>[10];
MyClass<?> gens[] = new MyClass<?>[10]; // OK
}
}