java泛型(二)

一.概述

上一篇学习了泛型的基本使用和一些限制,这篇继续上一次没有学完的一些内容。Java泛型(一)
注意当类型参数存在继承关系的时候,同样类型之间不存在继承关系。Pair<Emploee>和Pair<Manager>并不存在继承关系。但是List<String>和ArrayList<String>是存在继承关系的。

二.通配符类型

1.通配符子类型限定

上一节学习其实已经涉及到通配符的使用了,例如:Pair<? extends Emploee>
但是这样会有一个问题当使用set方法的时候是报告类型错误,因为set(Pair<? extends Emploee> p) 方法只知道参数是Emploee的一个自类型,但是具体的子类型是无法确定的,但是get获取到的返回值是可以赋值给Emploee的,虽然不知道具体类型,但是可以确定是Emploee的子类型。

2.通配符超类型限定

和通配符子类型限定很相像。Pair<? super Manage> 表示限定为Manger的超类。
但不同的是它可以作为set方法的参数因为可以确定的是只要是Manager类型的父类就可以传入,但是get方法就不行了,因为无法确定是Manger父类的具体类型。
通过前两点可以总结为:带有超类型限定的通配符可以向泛型对象写入 ,带有子类型限定的通配符可以从泛型对象读取。

3.无限定通配符

无限定就是类型参数只用?代表。Pair<?>表示无限定通配符。
看起来和Pair类型一样,但还是有很大的区别的,它里面存在两个方法:

? getFirst()
void setFirst(?)

这样get方法只能接收Object类型的变量,而不是任意对象。set的方法无法调用,由于无法确定具体类型。

4.通配符的捕获

通配符捕获只有在许多限制的情况下才是合法的。编译器必须能够确信通配符表达的是单个、确定的类型。

import com.gyx.demo.chapter6.Employee;
import com.gyx.demo.chapter6.Manager;

/**
 * 通配符实例
 */
public class PairDemo {
	public static void main(String[] args) {

		Manager ceo = new Manager("a",2000);
		Manager cfo = new Manager("b",500);
		Pair<Manager> buddies = new Pair<>(ceo,cfo);
		printBuddies(buddies);

		ceo.setBonus(3000);
		cfo.setBonus(2000);

		Manager[] managers = {ceo,cfo};

		Pair<Employee> result = new Pair<>();
		minmaxBonus(managers,result);
		System.out.println("first: " + result.getFirst().getName() + ",second: " + result.getSecond().getName());

		maxminBonus(managers,result);
		System.out.println("first: " + result.getFirst().getName() + ",second: " + result.getSecond().getName());
	}

	/**
	 * 这个方法如果传入Pair<Manager>类型就会报错
	 * 可以使用通配符来解除这一个限制
	 * 将Pair<Employee>换成Pair<? extends Employee>这样是Employee的子类都可以传递了
	 */
	public static void printBuddies(Pair<? extends Employee> p) {
		Employee first = p.getFirst();
		Employee second = p.getSecond();
		System.out.println(first.getName() + " and " + second.getName() + " are buddies.");
	}

	/**
	 * 通配符超类型限定
	 * @param a
	 * @param result
	 */
	public static void minmaxBonus(Manager[] a, Pair<? super Manager> result) {
		if (a.length == 0) {
			return;
		}
		Manager min = a[0];
		Manager max = a[0];
		for (int i = 0; i < a.length; i++) {
			if (min.getBonus() > a[i].getBonus()) {
				min = a[i];
			}
			if (max.getBonus() < a[i].getBonus()) {
				max = a[i];
			}
		}
		result.setFirst(min);
		result.setSecond(max);
	}

	public static void maxminBonus(Manager[] a, Pair<? super Manager> result) {
		minmaxBonus(a, result);
		//
		PairAlg.swapHelper(result);
	}
}

class PairAlg {
	/**
	 * 无限定通配符的作用
	 * 它可以用来判断一个类型是否含有null引用。
	 * @param p
	 * @return
	 */
	public static boolean hasNulls(Pair<?> p) {
		return p.getFirst() == null || p.getSecond() == null;
	}

	/**
	 * 因为不能使用?号作为类型定义,但交换的时候还需要保存第一个元素。
	 * @param p
	 */
	public static void swap(Pair<?> p) {
		swapHelper(p);
	}

	/**
	 * 编写一个辅助方法,它与swap方法的区别是:
	 * 它是一个泛型方法,但是swap不是,它是一个具有固定的Pair<?>类型的参数
	 * 这样可以使用T来捕获?的通配符参数类型
	 * @param p
	 * @param <T>
	 */
	public static <T> void swapHelper(Pair<T> p) {
		T t = p.getFirst();
		p.setFirst(p.getSecond());
		p.setSecond(t);
	}
}

三.反射和泛型

列举一个书中的实例查询出类中的所有泛型方法,具体方法可以自行查询API来查询一下。

import java.lang.reflect.*;
import java.util.*;


/**
 * 反射与泛型实例
 * 查询出泛型类中所有的泛型方法
 */
public class GenericReflectionDemo {

	public static void main(String[] args) {
		String name;
		if (args.length > 0) {
			name = args[0];
		} else {
			try (Scanner in = new Scanner(System.in)) {
				System.out.println("Enter class name (e.g java.util.Collections): ");
				name = in.next();
			}
		}
		try {
			Class<?> cl = Class.forName(name);
			printClass(cl);
			for (Method method : cl.getDeclaredMethods()) {
				printMethod(method);
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	public static void printClass(Class<?> cl) {
		System.out.print(cl);
		printTypes(cl.getTypeParameters(), "<", ", ", ">", true);
		Type sc = cl.getGenericSuperclass();
		if (sc != null) {
			System.out.print(" extends ");
			printType(sc, false);
		}
		printTypes(cl.getGenericInterfaces(), " implements ", ", ", "", false);
		System.out.println();
	}

	public static void printMethod(Method m) {
		String name = m.getName();
		System.out.print(Modifier.toString(m.getModifiers()));
		System.out.print(" ");
		printTypes(m.getTypeParameters(), "<",", ",">",true);

		printType(m.getGenericReturnType(),false);
		System.out.print(" ");
		System.out.print(name);
		System.out.print("(");
		printTypes(m.getGenericParameterTypes(),"",", ","",false);
		System.out.println(")");
	}

	public static void printTypes(Type[] types, String pre, String sep, String suf, boolean isDefinition) {
		if (" extends ".equals(pre) && Arrays.equals(types, new Type[]{Object.class})) {
			return;
		}
		if (types.length > 0) {
			System.out.print(pre);
		}
		for (int i = 0; i < types.length; i++) {
			if (i > 0) {
				System.out.print(sep);
			}
			printType(types[i], isDefinition);
		}
		if (types.length > 0) {
			System.out.print(suf);
		}
	}

	public static void printType(Type type, boolean isDefinition) {
		if (type instanceof Class) {
			Class<?> t = (Class<?>) type;
			System.out.print(t.getName());
		} else if (type instanceof TypeVariable) {
			// 描述类型变量
			TypeVariable<?> t = (TypeVariable<?>) type;
			System.out.print(t.getName());
			if (isDefinition) {
				printTypes(t.getBounds(), " extends ", " & ", "", false);
			}
		} else if (type instanceof WildcardType) {
			// 描述通配符
			WildcardType t = (WildcardType) type;
			System.out.print("?");
			printTypes(t.getUpperBounds(), " extents ", " & ", "", false);
			printTypes(t.getLowerBounds(), " super ", " & ", "", false);
		} else if (type instanceof ParameterizedType) {
			// 描述泛型类或接口类型
			ParameterizedType t = (ParameterizedType) type;
			Type owner = t.getOwnerType();
			if (owner != null) {
				printType(owner, false);
				System.out.print(".");
			}
			printType(t.getRawType(), false);
			printTypes(t.getActualTypeArguments(), "<", ", ", ">", false);
		} else if (type instanceof GenericArrayType) {
			// 描述泛型数组
			GenericArrayType t = (GenericArrayType) type;
			System.out.print("");
			printType(t.getGenericComponentType(), isDefinition);
			System.out.print("[]");
		}
	}
}

四.总结

这两节说的都比较笼统,只是说了一些基本使用,和一些限制,高级用法说的基本也都是书中讲解的,再加上一些个人的理解在里面。等以后确实用到比较多的时候,或者又一些更高的感悟的时候也会回来修改的。
下一篇学习泛型使用最多的集合类,这部分会分成好几篇来学习,内容比较多,花费时间也比较多,当然还是以基本使用为主,原理性的东西也会涉及到一点点。
有些可能我理解的不够深刻,大家如果觉得我说的不够详细可以参考我的推荐书,详细的看一下。欢迎大家评论。第一时间我会回复大家。谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值