/**
 * 看看下面的代码,使用类型参数T定义了一个max局部变量,这就意味着max可以是任意类型的
 * 那么max.compareTo(array[i])方法的调用的前提是T所属的类中有compareTo方法
 * 可以对这个代码进行改善
 */
public class WildCard {

	public static <T>T max(T[] array) {
		
		if ( null == array || 0 == array.length) {
			return null;
		}
		
		T max = array[0];
		
		for (int i = 1; i < array.length; i++) {
			
			 if (max.compareTo(array[i]) < 0) {max = array[i];} 
		}
		
		return max;
	}
}


/**
 * 看看下面的代码,使用类型参数T定义了一个max局部变量,这就意味着max可以是任意类型的
 * 那么max.compareTo(array[i])方法的调用的前提是T所属的类中有compareTo方法
 * 我们定义类型参数的变化,<T extends Comparable<T>>这里将T类型限定在Comparable
 * 及其所有的子类,可是这里Comparable是一个interface,为什么这里用extends呢?
 * 
 * <T extends Bounding type>表示T类型应该是绑定类型及其子类型subtype,T和绑定类型可以是类或者接口
 * 使用extends是因为它更接近子类的概念
 */
public class WildCard {

	public static <T extends Comparable<T>>T max(T[] array) {
		
		if ( null == array || 0 == array.length) {
			return null;
		}
		
		T max = array[0];
		
		for (int i = 1; i < array.length; i++) {
			
			 if (max.compareTo(array[i]) < 0) {max = array[i];} 
		}
		
		return max;
	}
}



import java.io.Serializable;
import java.util.ArrayList;

/**
 * 如果限定T为class的时候,就有一个非常严格的规则,这个class智能放在第一个,最多只能有一个class
 * 这样一来就能够严格控制T类型是单继承的,遵循Java规范
 * 
 * 1) 类型限定只能限定某个类型及其子类,使用关键字extends;
 * 2) 多个类型参数用逗号分隔,多个限定类型用&隔开
 * 3) 限定interface的时候,对interface的个数和顺序无严格要求,限定class的时候,则需要
 *    将class类型置于第一个位置,且最多只能存在一个class类型
 * 
 */
public class WildCard {

	public static <T extends ArrayList &Runnable &Serializable> T max(T[] array) {
		
    return null;
	}
}

/**
 * 面向接口编程,而非面向过程编程,这个设计原则,方法调用通过高层的抽象类或者接口来进行,具体调用的方法体
 * 就是我们实际运行时期传递的具体实现类的实例,这也是多态的一种体现,我们就需要通过子类来调用方法,而调用
 * 的方法体现这个类的超类的实例,继承结构越往上就可能是abstract的,或是interface,抽象类和接口是无法
 * 实例化的,这种反设计让调用面临失败,一旦限定的这个类就是抽象的或是接口,这个会造成这个泛型类或泛型方法
 * 无法使用,导致设计失败;
 * 
 * 所以public static <T super Runnable> void test(T runner) 这是行不通的
 * 这种功能可以通过泛型中的通配符来得到解决;
 * 通配符类型,相比于固定的泛型类型,它是一个巧妙的解决方案::
 * 
 * 表示Couple的泛型类型是Employee或者子类,Couple<Manager>满足,而Couple<File>不满足
 * 使用同配置?来表示::
 */
public class WildCard {

	// The type T is not generic; it cannot be parameterized with arguments <? extends Employee>
	// ? extends Employee 自身不能单独使用,可以理解为只能寄生在其他泛型类中,作为泛型类一个具体的类型参数,通常用于定义阶段
	// public class Couple<T>
	
	// public static ? extends Employee {....} (错误)
	// 使用通配符来定义方法返回值和方法的参数类型在Java中是不允许的!!!
	// 和前面子类型的限定一样,用?表示通配符,它的存在必须存在泛型类的类型参数中Couple<? super Manager>
	public static <T extends ArrayList &Runnable &Serializable> T max(Couple<? extends Employee> couple) {
	
	  Employee wife = couple.getWife();
	  
    return null;
	}
}



/**
 * 泛型参数的限定,使用extends 关键字,限定多个类型时候用&隔开,如<T extends Runnable& Serializable>
 * 泛型参数限定中,如果限定的类型是class而不是interface,则class必须放在限定类表中的第一个,且最多只能存在一个class
 * 通配符只能用在泛型类的泛型参数中,不能单独使用
 * Couple<?> Couple<? extends Employee> Couple<? super Manager>
 * 通配符的超类型限定适用于写入,通配符的子类型限定适用于读取,无限定通配符使用一些非null判断等简单操作
 */
public class WildCard {

	public static <T extends ArrayList &Runnable &Serializable> T max(Couple<? extends Employee> couple) {
	
	  Employee wife = couple.getWife();
	  
      return null;
	}
	
	public void callWildcard() 
	{
		WildCard.max(null);
	}
}