Java泛型类型擦除是指在编译时,将泛型类型参数转换为它的限定类型,以便在运行时可以使用。这是因为Java虚拟机(JVM)不能直接处理泛型类型,因此必须将其转换为其他形式才能在JVM上运行。
Java泛型类型擦除的好处是它可以使代码变得更加通用,因为它不会强制要求使用特定的数据类型。例如,如果你想要创建一个方法来处理任意数量的对象,你可以使用泛型来定义该方法,而不必明确地声明要处理的对象的数量或类型。
此外,Java泛型类型擦除也有一些弊端。例如,当你尝试在运行时检测一个对象的数据类型时(例如使用instanceof关键字),你会遇到问题。这是因为在运行时所有的泛型都已被“擦除”了(即已被转化成Object或原始数据类型)。
public class GenericTypeErasure { public static void main(String[] args) { List<Integer> list = new ArrayList<Integer>(); list.add(1); if (list.get(0) instanceof Integer) { System.out.println("It is an Integer"); } else { System.out.println("It is not an Integer"); } } }
上面的代码中list中存储了一个Integer对象(即1)。然而当我们尝试使用instanceof关键字来测试list中存储的对象是否是Integer时会出问题。这是因为instanceof关键字会尝试匹配原始数据类型而不是泛型数据类型。因此上述代码将打印“It is not an Integer”而不是“It is an Integer”。
术语泛型意味着参数化类型。使用泛型,可以创建与不同类型的数据一起使用的单个类。在参数化类型上操作的类,接口或方法称为通用。
以下是声明通用类的语法:
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
用于声明一个对象。泛型只与对象一起工作通用类型根据其类型参数而有所不同。
上面的代码生成以下结果。
您可以在泛型类型中声明多个类型参数。
// 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); } }
上面的代码生成以下结果。
以下代码声明并使用队列<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); } }
输出:
JPA教程 -JPA列唯一可空例子我们可以设置映射列是否可以具有空值或者列是否应该具有唯一值。@Column(unique=true, nullable=fals...
JPA教程 -JPA日期映射到时间戳示例我们可以使用以下代码将Java Date类型值映射到TIMESTAMP类型数据库表列。@Temporal(TemporalTy...
JPA教程 -JPA单向一对一映射示例以下代码显示了如何进行单向一对一映射。例子下面的代码来自PersonDaoImpl.java。package cn..co...