Java泛型到底什么,在看《数据结构与算法分析》一书时我不禁问自己。其书中介绍甚为抽象,本人就想试着用程序实验一下java泛型。参考了小顾问@cnblogs的关于java泛型的博文。本人的理解Java泛型其实就是参数类型的类型。
/** * * @author wqh * 泛型基础 */
public class GenericDemo1 {
/** * 未使用泛型 */
public static void test0() {
Map m = new HashMap();
m.put("key", "yes");
String s = (String) m.get("key");// 类型强制转换
}
/** * 未使用泛型 * 没进行型强制转换,无法通过编译 */
public static void test1() {
Map m = new HashMap();
m.put("key", "yes");
//String s = m.get("key");// 无类型强制转换,编译无法通过
}
/** * 未使用泛型 * map中保存了Integer类型的对象,运行时抛出 ClassCastException */
public static void test2() {
Map m = new HashMap();
m.put("key", new Integer(3));// 值可为任意对象,编译可以通过
String s = (String) m.get("key");// 类型强制转换
}
/** * 使用泛型 * 注意Map的声明,声明时就指定了变量的类型, * Map<String, String>类型的对象,Map.put()方法参数类型必须为String, * Map.get()方法 将会得到 String 类型. * map中保存了Integer类型的对象,编译无法通过 */
public static void test3() {
Map<String, String> m = new HashMap<String, String>();// 使用泛型
// m.put("key", new Integer(3));//编译无法通过
String s = m.get("key");// 不需要类型强制转换
}
/** * 使用泛型 * */
public static void test4() {
Map<String, String> m = new HashMap<String, String>();// 使用泛型
m.put("key", "yes");// 编译通过
String s = m.get("key");// 不需要类型强制转换
}
public static void main(String[] args) {
test2();//抛出 ClassCastException
}
/** * 以上代码可以看出,如果使用泛型 * 1.保存在Map中值的类型错误时不能编译通过,类型安全 * 2.在获取值时不需要进行强制类型转换,提高可靠性并加快开发速度 * 结论:泛型消除代码中的强制类型转换,并且进行类型检查!!! */
}
/** * * @author wqh * 泛型通配符 */
public class GenericDemo2 {
/** * 数组是协变的,意思是在可以需要用numberArray的地方使用intArray */
private void test0() {
Integer[] intArray = new Integer[10];
Number[] numberArray = intArray;
}
/** * 泛型不是协变的,不可以在需要listObject的地方使用listString * String是Object的子类,但是List<String>和List<Object>却没有这种继承关系 */
public static void test1(){
List<Object> listObject = new ArrayList<Object>();
List<String> listString = new ArrayList<String>();
}
/** * 如果泛型协变的,就会违背泛型应该提供的类型安全 * Integer和Float不是同一种类型 */
public void test2() {
List<Integer> intList = new ArrayList<Integer>();
List<Number> numberList = intList; // 编译不通过,无效代码
numberList.add(new Float(3.1415));//违背泛型应该提供的类型安全
}
/** * printList1方法的参数类型只能是List<Object>,调用时传入List<Integer>编译不能通过 * */
public void printList1(List<Object> l) {
for (Object o : l){
System.out.println(o);
}
}
/** * 为了灵活使用泛型,引入类型通配符。 * printList2方法的参数类型可以是 * List<Object>、List<Integer> 或 List<List<List<Object>>> * */
public void printList2(List<?> l) {
for (Object o : l) {
System.out.println(o);
}
}
/** * 类型通配符?的作用 * 编译器不知道 List的类型参数的值,但是编译器可以推理, * 它推断未知的类型参数必须扩展 Object * 1.但是编译器不能对 List的类型参数作出足够严密的推理, * 以确定将 Integer 传递给 List.add() 是类型安全的 * 所以lu.add的方法编译不通过 * 2.不依赖于编译器必须知道关于lu的类型参数的方法 * 则是可以编译通过的,例如lu.clear() */
public void test4() {
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
List<?> lu = li;
System.out.println(lu.get(0));
lu.add(new Integer(4)); // 编译无法通过
lu.clear();
}
}
/** * * @author wqh * 泛型方法 * */
public class GenericDemo3 {
/** * 泛型方法是为了想要在该方法的多个参数之间宣称一个类型约束 * ifThenElse方法不用显式地告诉编译器T是什么值, * 编译器可以使用类型推理来推断出 */
public <T> T ifThenElse(boolean b, T first, T second) {
return b ? first : second;
}
/** * 调用方法ifThenElse */
private void test0() {
String s1 =
ifThenElse(true, "a", "b");
//编译通过:"a","b"是String类型,类型相同
Integer i =
ifThenElse(false, new Integer(1), new Integer(2));
//编译通过:new Integer(1), new Integer(2)
//是Integer类型
String s2 =
ifThenElse(false, "pi", new Float(3.14));
//编译不通过:"pi", new Float(3.14)类型不同
}
/** * 在还没有完全指定类型参数时,需要对类型参数指定附加的约束 * 类型参数 V 被判断为由 Number限制 。 * 在没有类型限制时,假设类型参数由 Object限制 */
public class Matrix<V extends Number> { }
/** * 允许创建Matrix<Number>、Matrix<Integer>类型的对象, * 但是不允许创建Matrix<String>的对象 */
private void test1() {
new Matrix<Number>();//编译通过
new Matrix<Integer>();//编译通过
new Matrix<String>();//编译不通过
}
}
/** * * @author wqh * 泛型高级 * 此部分内容本人理解也不是很好,不是很详尽,Selector的东西还需要研究 */
public class GenericDemo4 {
/** * Java类库中的泛型 * 该定义组合了通配符类型参数和有限制类型参数, * 允许您将 Collection<Integer> 的内容添加到 Collection<Number>。 */
interface Collection<V> {
boolean addAll(Collection<? extends V> paramCollection);
}
/** * 二元 max() 方法的实现 * 使用泛型方法和有限制类型参数 */
public static <T extends Comparable<T>> T max(T t1, T t2) {
if (t1.compareTo(t2) > 0)
return t1;
else
return t2;
}
/** * 让 T.class是 Class<T> 类型的好处是,通过类型推理, * 可以提高使用反射的代码的类型安全 * 还不需要将 T.class.newInstance()强制类型转换为T * 此方法实现从数据库检索一组对象,并返回 JavaBeans 对象的一个集合 * @throws IllegalAccessException * @throws InstantiationException */
public static <T> List<T> getRecords(Class<T> c, Selector s) throws
InstantiationException, IllegalAccessException {
// Use Selector to select rows
List<T> list = new ArrayList<T>();
for (/* iterate over results */;;) {
T row = c.newInstance();
// use reflection to set fields from result
list.add(row);
}
}
/** * 用 Class<T> 替换 T[] * Collection 接口还没有改变为使用该技术, * 因为这会破坏许多现有的集合实现 * 但是如果使用泛型从新构建 Collection, * 则当然会使用该方言来指定它想要返回值是哪种类型。 * 调用:Integer[] integer = new GenericDemo4().toArray(Integer.class); * */
public <T> T[] toArray(Class<T> returnType) {
//未实现
return null;
}
}
/** * * @author 小顾问@cnblogs * * @param <V> * 一个简单的泛型类,类似于 List,充当一个容器 * 泛型类最常见的用例是容器类(比如集合框架) * 或者值持有者类(比如 WeakReference 或 ThreadLocal) */
public class SimpleGenericList<V> {
private V[] array;
private int size;
public SimpleGenericList(int capacity) {
array = (V[]) new Object[capacity];
//List构造函数的一种可能的实现
}
public void add(V value) {
if (size == array.length)
throw new IndexOutOfBoundsException(Integer.toString(size));
else if (value == null)
throw new NullPointerException();
array[size++] = value;
}
public void remove(V value) {
int removalCount = 0;
for (int i = 0; i < size; i++) {
if (array[i].equals(value))
++removalCount;
else if (removalCount > 0) {
array[i - removalCount] = array[i];
array[i] = null;
}
}
size -= removalCount;
}
public int size() {
return size;
}
public V get(int i) {
if (i >= size)
throw new IndexOutOfBoundsException(Integer.toString(i));
return array[i];
}
}
/** * * @author 小顾问@cnblogs * 作为从原始集合类型迁移到泛型集合类型的帮助, * 集合框架添加了一些新的集合包装器, * 以便为一些类型安全 bug 提供早期警告 */ public class Collections { public static <E> Collection<E> checkedCollection(Collection<E> c, Class<E> type ) { return new CheckedCollection<E>(c, type); } //省略了部分Collection<E>中定义的接口的实现 private static class CheckedCollection<E> implements Collection<E> { private final Collection<E> c; private final Class<E> type; CheckedCollection(Collection<E> c, Class<E> type) { this.c = c; this.type = type; } public boolean add(E o) { if (!type.isInstance(o)) throw new ClassCastException(); else return c.add(o); } } }