Java基础学习笔记:第九章 泛型

为什么要有泛型(Generic)?

  1. 解决元素存储的安全性问题
  2. 解决获取数据元素时,需要类型强转的问题
    泛型,JDK1.5新加入的,解决数据类型的安全性问题,其主要原理是在类声明时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这样在类声明或实例化时只要指定好需要的具体的类型即可。
    Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException异常。同时,代码更加简洁、健壮。

在这里插入图片描述
在这里插入图片描述

使用泛型

1.泛型的声明

	interface List<T> 和 class TestGen<K,V> 
	其中,T,K,V不代表值,而是表示类型。这里使
    用任意字母都可以。常用T表示,是Type的缩写。

2.泛型的实例化:

     一定要在类名后面指定类型参数的值(类型)。如:
     List<String> strList = new ArrayList<String>();
     Iterator<Customer> iterator = customers.iterator();
     T只能是类,不能用基本数据类型填充。

泛型的几个重要使用

对于泛型类(含集合类)

1.对象实例化时不指定泛型,默认为:Object。
2.泛型不同的引用不能相互赋值。
3.加入集合中的对象类型必须与指定的泛型类型一致。
4.静态方法中不能使用类的泛型。
5.如果泛型类是一个接口或抽象类,则不可创建泛型类的对象。
6.不能在catch中使用泛型
7.从泛型类派生子类,泛型类型可以具体化

在这里插入图片描述

自定义泛型类

class Person<T>{
	//使用T类型定义变量
	private T info;
	//使用T类型定义一般方法
	public T getInfo(){
		return info;
	}
	public void setInfo(T info){
		this.info = info;
	}
//使用T类型定义构造器
public Person(){}
public Person(T info){
	this.info = info;
}
//static的方法中不能声明泛型
//public static void show(T t){
//}
//不能在try-catch中使用泛型定义
//try{}
//catch(T t){}		
}

对于泛型方法

方法,也可以被泛型化,不管此时定义在其中的类是不是泛型化的。在泛型方法中可以定义泛型参数,此时,参数的类型就是传入数据的类型。
泛型方法的格式:
[访问权限] <泛型> 返回类型 方法名([泛型标识 参数名称]) 抛出的异常

public class DAO {
	
	public <E>  E get(int id, E e){
		
		E result = null;
		
		return result;
	}
}

static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
	for (T o : a) {
		c.add(o);
	}	}
public static void main(String[] args) {
	Object[] ao = new Object[100];
	Collection<Object> co = new ArrayList<Object>();
	fromArrayToCollection(ao, co);

	String[] sa = new String[20];
	Collection<String> cs = new ArrayList<>();
	fromArrayToCollection(sa, cs);

	Collection<Double> cd = new ArrayList<>();
	// 下面代码中T是Double类,但sa是String类型,编译错误。
	// fromArrayToCollection(sa, cd);
	// 下面代码中T是Object类型,sa是String类型,可以赋值成功。
	fromArrayToCollection(sa, co);  
}


泛型和继承的关系

如果B是A的一个子类型(子类或者子接口),而G是具有泛型声明的类或接口,G并不是G的子类型!

比如:String是Object的子类,但是List并不是List的子类。

public void testGenericAndSubClass() {
	// 在泛型的集合上
	List<Person> personList = null;
	List<Man> manList = null;
	// personList = manList;(报错)
}

通配符

1.使用类型通配符:?
比如:List<?> ,Map<?,?>
List<?>是List、List等各种泛型List的父类。

2.读取List<?>的对象list中的元素时,永远是安全的,因为不管list的真实类型是什么,它包含的都是Object。

3.写入list中的元素时,不行。因为我们不知道c的元素类型,我们不能向其中添加对象。
唯一的例外是null,它是所有类型的成员。

将任意元素加入到其中不是类型安全的:

Collection<?> c = new ArrayList<String>();
c.add(new Object()); // 编译时错误

因为我们不知道c的元素类型,我们不能向其中添加对象。
add方法有类型参数E作为集合的元素类型。我们传给add的任何参数都必须是一个未知类型的子类。因为我们不知道那是什么类型,所以我们无法传任何东西进去。
唯一的例外的是null,它是所有类型的成员。

另一方面,我们可以调用get()方法并使用其返回值。返回值是一个未知的类型,但是我们知道,它总是一个Object

public static void main(String[] args) {
	List<?> list = null;
	list = new ArrayList<String>();
	list = new ArrayList<Double>();
	//list.add(3);
	list.add(null);
		
	List<String> l1 = new ArrayList<String>();
	List<Integer> l2 = new ArrayList<Integer>();
	l1.add(“尚硅谷");
	l2.add(15);
	read(l1);
	read(l2);  }
	static void read(List<?> list){
		for(Object o : list){
			System.out.println(o);
	}  
}
有限制的通配符
<?>

允许所有泛型的引用调用
举例:

<? extends Number>     (无穷小 , Number]
只允许泛型为Number及Number子类的引用调用

<? super Number>      [Number , 无穷大)
只允许泛型为Number及Number父类的引用调用

<? extends Comparable>
只允许泛型为实现Comparable接口的实现类的引用调用
public static void printCollection3(Collection<? extends Person> coll){
	//Iterator只能用Iterator<?>或Iterator<? extends Person>.why?
	Iterator<?> iterator  = coll.iterator();
	while(iterator.hasNext()){
		System.out.println(iterator.next());
	}   
}
public static void printCollection4(Collection<? super Person> coll){
	Iterator<?> iterator  = coll.iterator();
	while(iterator.hasNext()){
		System.out.println(iterator.next());
	}   
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值