泛型定义

方法的参数及返回值一般是具体的某个类或某个接口。 (接口的好处是多态)。

 

当方法的参数或返回值是允许是多种不同的类型时,只能使用Object对象。

如:实例化某一个类:

 

public Object createJavaBean(Class classz) throws Exception{
		return classz.newInstance();
	}
//调用时需使用 Person person =(Person)createJavaBean(Person.class);
//              Dog dog= (Dog)createJavaBean(Dog.class);
//              Cat cat = (Cat)creatJavaBean(Cat.clas);
// createJavaBean 可以生成不同类型的实例,在调用时才能根据参数确定其正确的返回值类型。
 返回值为Object ,需要将类型强制转换为实际的类型。

 

如果这是一个常被调用的方法,其他人调用时,需要查看方法代码才能明白返回的Object是什么。

因此最好使用泛型:IDE能够提示传入或返回正确的类型,而不用强制类型转换。

 

泛型类:一个类可以操作多个不同类型对象时(每个类实例对应的类型固定),类定义时不能明确的方法的参与返回值类型,则可以将不确定的类型定义为类型参数(代替了Object),定义了类型参数的类为泛型类。

 

 泛型类说明它操作或方法返回的类型不确定,直到实例化时(传入实际的类型参数值)才确定,该实例的所有方法都能明确其返回值或参数值的类型(写代码时IDE直接提示该类型是什么了),而不是Object。

 

泛型方法:方法的参数或返回值的类型不确定,可以定义为类型参数(而不是Object),直到方法调用时,传入实际的参数类型,从而推导出实际的返回值类型,或推导出其它的参数的类型(写代码时IDE直接提示该类型是什么了),而不是Object。

 

 

泛型方法:

方法的返回值前定义泛型说明: < 类型参数A[A extends  类或另一类型参数][,类型参数B[B extends 类或另一类型参数]....]>,方法参数类型或返回值类型 定义好的类型参数A或B了。

 

public  T createJavaBean(Class classz) throws Exception{
		return classz.newInstance();
}
//定义了T类型,说明参数是某一类的Class对象,返回值类型则为该类型的实例。
//那么传入的参数类型一确定,那么它的返回值类型也就确定了。所以返回值不是Object,而是实际的类型。

//调用时:Person person = createPerson(Person.class);而不需要类型转换
 如果createJavaBean 只能够创建Person 及其子类型 ,其它的类型不能创建 。那么就应该定义T类型的范围 : T extends Person,说明T只能是Person 或其子类型。
public  T createPerson(Class classz) throws Exception{
		return classz.newInstance();
}
调用:BlackPerson blacPerson = createPerson(BlackPerson.class);
				//BlackPerson是Person 的子类。
				createPerson(String.class);//这行编译报错
	
 

 泛型类:

   在类名后面加上泛型说明: < 类型参数A[A extends  类或另一类型参数][,类型参数B[B extends 类或另一类型参数]....]>,类中的任意方法的参数或返回值就可以使用类型参数A或B了。

 

类型参数值在泛型类实例化时确定: new 泛型类<实际类型参数A,实际类型参数B....>(构建器参数)。

实例化之后,方法的参数与返回值是类型参数的,都已明确它的类型=实际传入的类型

   


泛型定义_第1张图片
 在实例化泛型类时,也可以不传入实际的类型参数,那么类中定义的类型参数就自动为Object.


泛型定义_第2张图片
 泛型类的子类:

第一种方式,扩展父类,给出实际的参数类型:


泛型定义_第3张图片
 第二种方式:继续使用参数类型


泛型定义_第4张图片
 

类型通配符:?

代表任意类型。 

 一般用于泛形类实例变量。

 List list ;//不明确类型的List,

list = new ArrayList();//正确

list = new ArrayList();//正确

list = new ArrayList();//正确

可以用于方法参数中,实现对某一个类的不同泛型类实例的通用操作,但只能调用泛型实例的非泛型参数的方法,因为泛型参数是?,无法确定其类型,参数传递不进去。

 

 void test(List list){
		Object obj = list.get(0);//调用非泛型方法,返回值类型为?,未明确的类型,上溯到所有类型的父类Object
		list.add(new String(""));//调用泛型方法,参数类型是?,未明确的类型,可能是String、Integer等等,这行代码中给?赋值为String,编译不过去
	}

  

void test(List list){
		Person person = list.get(0);//调用非泛型方法,返回值类型为?,未明确的类型,上溯到类型上限 Person 
		//list.add(new Person());//调用泛型方法,编译不过去
	}

 

 

 

 

AbstractCollection 源码:

 

 

public abstract class AbstractCollection implements Collection {
    public boolean containsAll(Collection c) {
	Iterator e = c.iterator();
	while (e.hasNext())
	    if (!contains(e.next()))
		return false;
	return true;
    }
       public boolean contains(Object o) {
	Iterator e = iterator();
	if (o==null) {
	    while (e.hasNext())
		if (e.next()==null)
		    return true;
	} else {
	    while (e.hasNext())
		if (o.equals(e.next()))
		    return true;
	}
	return false;
    }	
   public boolean addAll(Collection c) {
	boolean modified = false;
	Iterator e = c.iterator();
	while (e.hasNext()) {
	    if (add(e.next()))
		modified = true;
	}
	return modified;
    }
}
   源码中:

 

      1.方法 containsAll(Collection c) ,参数可以是任意类型的 Collection。

      2.方法addAll(Collection c),可以接受E类型或E子类型的Collection.

   

   

获取泛型实例的实际类型:

方式一:

父类 TypeReference ,来源于 MyBatis3.2.3

 

public abstract class TypeReference {
		 
		  private final Type rawType;//T的实际类型
		 
		  protected TypeReference() {
		    rawType = getSuperclassTypeParameter(getClass());
		  }
		 
		  Type getSuperclassTypeParameter(Class clazz) {
		    Type genericSuperclass = clazz.getGenericSuperclass();
		    if (genericSuperclass instanceof Class) {
		      // try to climb up the hierarchy until meet something useful
		      if (TypeReference.class != genericSuperclass) {
		        return getSuperclassTypeParameter(clazz.getSuperclass());
		      }
		 
		      throw new RuntimeException("'" + getClass() + "' extends TypeReference but misses the type parameter. "
		        + "Remove the extension or add a type parameter to it.");
		    }
		 
		    Type rawType = ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0];
		    // TODO remove this when Reflector is fixed to return Types
		    if (rawType instanceof ParameterizedType) {
		      rawType = ((ParameterizedType) rawType).getRawType();
		    }
		 
		    return rawType;
		  }
		 
		  public final Type getRawType() {
		    return rawType;
		  }
		 
		  @Override
		  public String toString() {
		    return rawType.toString();
		  }
		 
		
}
 DAO 类扩展 TypeReference:

 

 

 

public class Dao extends TypeReference{
	
	public T queryOne() throws Exception{
		T t = ((Class)this.getRawType()).newInstance();
		Map dataMap = new HashMap();//数据查询结果
		dataMap.put("name", "ll");//模拟数据
		BeanUtils.populate(t, dataMap);
		return t;
	}

}

 PersonDao 扩展了 Dao:

public class PersonDao extends Dao {//这里指明T的类型,要不然获取不到
	public static void main(String args []){
		try{
			PersonDao personDao = new PersonDao();
			Person person = personDao.queryOne();
			System.out.println(person);//输出:Person [name=ll]
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}

 

你可能感兴趣的:(JAVA-基础)