显示类型说明
Java 泛型 类型参数推断和显示类型说明
public class New {
/**
* 这就是类型推断
*/
public static <K, V> Map<K, V> map() {
return new HashMap<K, V>();
}
public static <T> List<T> list() {
return new ArrayList<T>();
}
public static <T> LinkedList<T> lList() {
return new LinkedList<T>();
}
public static <T> Set<T> set() {
return new HashSet<T>();
}
public static <T> Queue<T> queue() {
return new LinkedList<T>();
}
public static void main(String[] args) {
Map<Person, List<? extends Person>> pet = New.map();
f(pet);
// f(New.map()) 类型推断只对赋值操作有效。其他时候并不起作用
f(New.<Person, List<? extends Person>>map());// 显示的类型说明-- 静态方法在点(.)操作符前用类名,非静态this
}
static void f(Map<Person, List<? extends Person>> pet) {
System.out.println(pet);
}
}
注:
泛型方法使得该方法能够独立于类而产生变化,一下的一个基本的指导原则:无论何时,只要你能做到,你就应该尽量使用泛型方法。也就是说,如果使用泛型方法可以取代将整个类泛型化,那么久应该只使用泛型方法,因为它可以使事情更清楚明白。
擦除的补偿
泛型参数在创建对象的时候,不能直接使用new 关键字的方式创建
第一种模板方法
package generics;//: generics/CreatorGeneric.java
abstract class GenericWithCreate<T> {
final T element;
GenericWithCreate() { element = create(); }
abstract T create();
}
class X {}
class Creator extends GenericWithCreate<X> {
X create() { return new X(); }
void f() {
System.out.println(element.getClass().getSimpleName());
}
}
public class CreatorGeneric {
public static void main(String[] args) {
Creator c = new Creator();
c.f();
}
} /* Output:
X
*///:~
第二种工厂方法
package generics;//: generics/FactoryConstraint.java
interface FactoryI<T> {
T create();
}
class Foo2<T> {
private T x;
public <F extends FactoryI<T>> Foo2(F factory) {
x = factory.create();
}
// ...
}
class IntegerFactory implements FactoryI<Integer> {
public Integer create() {
return new Integer(0);
}
}
class Widget {
public static class Factory implements FactoryI<Widget> {
public Widget create() {
return new Widget();
}
}
}
public class FactoryConstraint {
public static void main(String[] args) {
new Foo2<Integer>(new IntegerFactory());
new Foo2<Widget>(new Widget.Factory());
}
} ///:~
第三种方法 Class.newInstance();方法
Class.newInstance()的方法,只有类存在默认的构造方法的时候,才能使用,不然会出现异常:
java.lang.RuntimeException: java.lang.InstantiationException: java.lang.Integer
package generics;//: generics/InstantiateGenericType.java
import static net.mindview.util.Print.*;
class ClassAsFactory<T> {
T x;
public ClassAsFactory(Class<T> kind) {
try {
x = kind.newInstance();
} catch(Exception e) {
throw new RuntimeException(e);
}
}
}
class Employee {}
public class InstantiateGenericType {
public static void main(String[] args) {
ClassAsFactory<Employee> fe =
new ClassAsFactory<Employee>(Employee.class);
print("ClassAsFactory<Employee> succeeded");
try {
ClassAsFactory<Integer> fi =
new ClassAsFactory<Integer>(Integer.class);
} catch(Exception e) {
print("ClassAsFactory<Integer> failed");
}
}
} /* Output:
ClassAsFactory<Employee> succeeded
ClassAsFactory<Integer> failed
*///:~
泛型的类型擦除引起的泛型数组问题
package generics;//: generics/GenericArrayWithTypeToken.java
import java.lang.reflect.*;
public class GenericArrayWithTypeToken<T> {
private T[] array;
@SuppressWarnings("unchecked")
public GenericArrayWithTypeToken(Class<T> type, int sz) {
array = (T[])Array.newInstance(type, sz);
//T[] array=new T[10];//这样的代码是不能编译的
//Object[] array = new Object[sz]; //这样数组添加和单个获取都问题,但是获取整个数组就会出现转型错误java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;
}
public void put(int index, T item) {
array[index] = item;
}
public T get(int index) { return array[index]; }
// Expose the underlying representation:
public T[] rep() { return array; }
public static void main(String[] args) {
GenericArrayWithTypeToken<Integer> gai =
new GenericArrayWithTypeToken<Integer>(
Integer.class, 10);
// This now works:
Integer[] ia = gai.rep();
}
} ///:~
泛型容器的问题
package generics;//: generics/GenericReading.java
import java.util.*;
public class GenericReading<T> {
static <T> T readExact(List<T> list) {
return list.get(0);
}
static <T> void add(List<T> list,T t) {
list.add(t);
}
// static List<Apple> apples = Arrays.asList(new Apple());//创建的为不能修改固定大小的List容器L,故不能执行新增
// static List<Fruit> fruit = Arrays.asList(new Fruit());
static List<Apple> apples = new ArrayList<Apple>();
static List<Fruit> fruit = new ArrayList<Fruit>();
static{
apples.add(new Apple());
fruit.add(new Fruit());
}
static void f1() {
Fruit a = readExact(apples);
Fruit f = readExact(fruit);
add(fruit, new Apple());
f = readExact(apples);
}
static class CovariantReader<T> {
//如果在类的泛型限定类中。 继承方式边界的泛型限定容器,可以传入类的泛型限定类的子类容器,
//如果不是类的泛型限定类中,则需要继承限定边界也能达到
T readCovariant(List<? extends T> list) {
return list.get(0);
}
//如果在类的泛型限定类中:逆变(超类型通配符),可以传入类的泛型限定类的子类容器,
如果不是类的泛型限定类中,则需要继承限定边界也能达到
void add(List<? super T> list, T t){
list.add(t);
}
}
static void f3() {
CovariantReader<Fruit> fruitReader =
new CovariantReader<Fruit>();
Fruit f = fruitReader.readCovariant(fruit);
Fruit a = fruitReader.readCovariant(apples);
fruitReader.add(fruit,new Apple());
System.out.println("");
}
public static void main(String[] args) {
f2();f3();
}
} ///:~