泛型的提出和学习

问题:使用ArrayList集合存储元素遍历的时候,按照正常的操作出现了问题,
当前ArrayList集合中存储了两种类型的元素分别String和Integer类型,在遍历的时候,使用的是String接收的,对于Integer类型就出现了异常!
 我们可以回想一下数组的特点:
String[ ] str = new String[3] ;
  str[0] = "you" ;
str[1] = "beautiful" ;
  str[2] = 500; 错误的,
 
我们知道数组直接定义了存储的类型,防止出现其他类型的元素,那么集合能不能也像数组一样,直接规定我们集合的存储类型呢?针对这种情况有一种技术可以解决这个问题。
 泛型
  <数据类型> --- 切记,一定是引用数据类型
 
 泛型:将明确集合类型的工作推迟到了创建对象或者调用方法的时候,属于一种参数化类型,可以作为参数传递.
 泛型的好处:
  1)将运行时期异常提前到了编译时期
  2)优化了设计,解决了黄色警告线问题
  3)避免了强制类型转换
 

 泛型的引出可以提高程序的安全性。

我们可以通过一段代码具体学习泛型

需求:使用ArrayList集合存储自定义对象并遍历,加入泛型

public class Student {
	
	private String name ;
	private int age ;
	
	public Student() {
		super();
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
public static void main(String[] args) {
		
		//创建集合对象
		ArrayList<Student> array = new ArrayList<Student>() ;  //=号右边的泛型:泛型推断
		
		//创建学生对象
		Student s1 = new Student("孙悟空",25) ; 
		Student s2 = new Student("猪八戒",27) ; 
		Student s3 = new Student("沙僧",29) ; 
		Student s4 = new Student("唐僧",30) ; 
		
		//添加到集合中
		array.add(s1) ;
		array.add(s2) ;
		array.add(s3) ;
		array.add(s4) ;
		
		//获取迭代器
		Iterator<Student> it = array.iterator() ;
		while(it.hasNext()) {
			Student s = it.next() ;
			System.out.println(s.getName()+"----"+s.getAge());
		}
		
		System.out.println("******************");
		
		//普通for循环
		for(int x = 0 ; x < array.size() ; x ++) {
			Student s = array.get(x) ;
			System.out.println(s.getName()+"---"+s.getAge());
		}
	}//孙悟空----25
        //猪八戒----27
        //沙僧----29
        //唐僧----30
        ******************
        //孙悟空---25
        //猪八戒---27
        //沙僧---29
        //唐僧---30
在早期的时候,使用Object类型代表任意类型,向上转型没有问题,

    使用向下转型的时候,可能会出现问题(需要的类型有问题),这个时候就需要引入泛型操作

我们可以看这样一个例子具体了解一下所描述的问题。

public class ObjectTool {
	
	private Object obj ;
	
	public Object getObj() {
		return obj ;
	}
	
	public void setObj(Object obj) {  //Object obj = new Integer() ;  //多态
		this.obj = obj ;
	}
public static void main(String[] args) {
		//创建ObjectTool该类 对象
		
		ObjectTool ot  = new ObjectTool() ;
		
		//赋值
		ot.setObj(new Integer(27));
		
		//获取值
		Integer i = (Integer) ot.getObj() ;  //向下转型
		System.out.println("年龄是:"+i);
		
		
              System.out.println("*************************");
ot.setObj(new String("高圆圆")) ;String s = (String)ot.getObj() ;System.out.println("姓名是:"+s);System.out.println("*************************");ot.setObj(new String("高圆圆"));Integer ii = (Integer)ot.getObj() ;System.out.println(ii);}

我们可以看到,编译没有问题,但是运行的时候出现了一个异常

java.lang.ClassCastException :程序不安全   :类转换异常 (转换不当),所以程序不安全,我们更想让程序在编译时期就提醒我们有错误,这样对开发者来说修改bug更方便。

我们将泛型加在类上试一下。

public class ObjectTool<T> {

	private T obj ;
	
	public T getObj() {
		return obj ;
	}
	
	public void setObj(T obj) {
		this.obj = obj ;
	}

我们可以看到,<T>就是泛型的标志。

public static void main(String[] args) {
		
		//创建ObjectTool对象
		ObjectTool<String> ot = new ObjectTool<String>() ;
		
		//赋值
		ot.setObj(new String("高圆圆"));
		String s = ot.getObj() ;
		System.out.println("姓名是:"+s);
		

		System.out.println("---------------");
		
		ObjectTool<Integer> ot2 = new ObjectTool<Integer>() ;
		ot2.setObj(new Integer(27));

		Integer i = ot2.getObj() ;
		System.out.println("年龄是:"+i);
	}//姓名是:高圆圆
        //---------------
        //年龄是:27

泛型也可以在方法上定义。

public <T> void show(T t) {
		System.out.println(t);
	}
	ObjectTool ot = new ObjectTool() ;
		ot.show("hello");
		ot.show(true);
		ot.show(100);	//hello
                                //true
                                //100
当没有泛型的时候,自建类中,需要使用方法重载定义三次show方法,然后在测试类中分别输出,
当我们在方法上定义泛型之后,大大减少了工作量,只需要在自建类中定义一个show方法,就可以在测试类中输出集中不同类型的数据。

泛型也可以定义在接口上,而且有两种方式,我们通过下面这段代码学习一下。

首先,创建一个接口,在接口上定义泛型;

public interface Inter<T> {

	//接口中变量是常量: public static final  int num ;
	
	public abstract void show() ; //抽象方法
//接口中泛型,子实现类的第一种情况,就是已经知道是什么类型了
public class InterImpl implements Inter<String> {

	@Override
	public void show() {
		System.out.println("hello");
	}
public static void main(String[] args) {
		
		//第一种情况的测试
		//创建接口的子实现类对象
		Inter<String> i = new InterImpl() ;
		i.show();//hello
第二种情况,在接口的子实现类中,并不知道是什么类型
public class InterImpl<T> implements Inter<T>{
	
	@Override
	public void show() {
		System.out.println("hello");
	}
Inter<Integer> i2 = new InterImpl<Integer>();
			i2.show() ;
			
		Inter<String> i3 = new InterImpl<String>() ;
		i3.show();
				//hello
                                //hello

我们再来看一下泛型高级(通配符)

<?>  :代表任意类型Object类型,或者任意的Java类 
<? extends E>:向下限定,E的子类或者E这个类型

 <? super E>:向上限定,E及其他的父类

我么看下面这段代码具体理解一下这三种通配符

public static void main(String[] args) {
		
		//创建集合对象,泛型如果明确的情况下,前后必须保持一致,不如c2,c3就会报错
		Collection<Object> c1 = new ArrayList<Object>() ;
//		Collection<Object> c2 = new ArrayList<Cat>() ;
//		Collection<Object> c3 = new ArrayList<Animal>() ;
		
		
		//<?>  :代表任意类型Object类型,或者任意的Java类 ,这就解决了上面的问题
		Collection<?> c4 = new ArrayList<Object>() ;
		Collection<?> c5 = new ArrayList<Animal>() ;
		Collection<?> c6 = new ArrayList<Dog>() ;
		Collection<?> c7= new ArrayList<Cat>() ;
		
//		<? extends E>:向下限定,E的子类或者E这个类型
		Collection<? extends Object> c8 = new ArrayList<Object>() ;
		Collection<? extends Object> c9 = new ArrayList<Animal>() ;
		Collection<? extends Object> c10 = new ArrayList<Cat>() ;
//		Collection<? extends Aninal> c11 = new ArrayList<Object>() ;因为Animal是Object的子类,
                                                                            //所以不能这样限定
		
//		<? super E>:向上限定,E及其他的父类
//		Collection<? super Animal> c12 = new ArrayList<Cat>() ;
		Collection<? super Animal> c13 = new ArrayList<Animal>() ;
		Collection<? super Animal> c14 = new ArrayList<Object>() ;
		
	}
}


class Animal{
	
}
class Cat extends Animal {
	
}

class Dog extends Animal{
	
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值