面向对象,Java泛型篇

 一、Java泛型入门基础

     1、 泛型历史:集合中可以存储任意类型对象,但是在取出时,如果要使用具体对象的特有方法时,需要进行向下转型,如果存储的对象类型不一致,在转型过程中就会出现ClassCastException异常。这样就给程序带来了不安全性。
在jdk1.5以后就有了解决方案——泛型技术:在存储元素时,就不允许存储不同类型的元素。存储了就编译失败。 所以就需要在存储元素时,在容器上明确具体的元素类型,这其实和数组定义很像。

      2、优势:1)将运行时期的ClassCastException异常转移到了编译时期,进行检查,并以编译失败来体现。 这样有利于程序员尽早解决问题。 
                2)避免了向下转型(强转)的麻烦。

      3、在什么情况下使用泛型呢?

              只要在使用类或者接口时,该类或者接口在api文当描述时都带着<>,就需要在使用时定义泛型。
其实,泛型无非就是通过<>定义了一个形式参数,专门用于接收具体的引用类型。在使用时,一定要传递对应的实际参数类型。
集合中泛型的应用特别多见。


 二、Java泛型使用

       使用泛型的动机举例(以集合为例):

class MySet:(自行写的MySet,实现的Java泛型)

public class MySet {
	private Object[] objs=new Object[0];
	public boolean add(E obj){
		if(contains(obj)){
			return false;
		}
		Object tempObjs[] = new Object[objs.length+1];
		System.arraycopy(objs, 0, tempObjs, 0, objs.length);
		tempObjs[objs.length] = obj;
		objs = tempObjs;
		return true;
	}
	
	public boolean contains(E obj){
		for(Object o:objs){
			if(o.equals(obj)){
				return true;
			}
		}
		return false;
	}
	public Object[] getAll(){
		return objs;
	}
	public int size(){
		return objs.length;
	}	
}
 

测试class:

import java.util.ArrayList;
import java.util.Iterator;
public class GenericDemo2 {
	public static void main(String[] args) {
//		MySet set = new MySet();
//		set.add("abcd");
//		set.add(8);//编译出错
		
//		MySet set = new MySet();
//		set.add("abcd");//编译出错
//		set.add(8);
	}
}

        注意:当一个变量被声明为泛型时,只能被实例变量和方法调用,而不能被静态变量和方法调用。原因很简单,参数化的泛型是一些实例。静态成员是被类的实例和参数化的类所共享的,所以静态成员不应该有类型参数和他们关联。
   

三、Java泛型类

       1、概念:当一个类要操作的引用数据类型不确定的时候,可以将该类型定义一个形参。用到的这类时,由使用者来通过传递类型参数的形式,来确定要操作的具体的对象类型。这意味着在定义这个类时,需要在类上定义形参,用于接收具体的类型实参。这就是将泛型定义在类上,即泛型类。

      2、什么时候使用泛型类呢?

           只要类中操作的引用数据类型不确定的时候,就可以定义泛型类。 有了泛型类,省去了曾经的强转和类型转换异常的麻烦。

代码示例:

/*
 * 泛型类的演示
 */
public class GenericDemo2 {
	public static void main(String[] args) {
		MyVessel u = new MyVessel();
		//u.setObject(new Student());//不行,u中存放的是Worker,实参只能是Worker类型
		u.setObject(new Worker());
		Worker w = u.getObject();
		System.out.println(w);
		
		MyVessel v = new MyVessel();
		//v.setObject(new Worker());//不行,实参只能是Student类型
	}

}
class MyVessel{ //从语法上讲把“E”取成别的名字如“QQ”也是可以的,但不规范。
	private E obj;
	public void setObject(E obj){
		this.obj = obj;
	}
	public E getObject(){
		return obj;
	}
}
class Student{
	String profession;
}
class Worker{
	String company; 
}

四、Java泛型方法

      1、泛型方法的定义(与类的泛型捆绑)

               方法要操作的类型不确定的,但是和调用该方法的对象指定的类型是一致。

      2、泛型方法的定义(独立于类的泛型)

               方法要操作的类型不确定的,而且不一定和调用该方法的对象指定的类型是一致。

      3、泛型方法的定义(静态方法的泛型)

               静态方法不能访问类上定义的泛型,因为它没有对象。如果静态方法需要泛型,该泛型只能定义在方法上。

代码示例:

class Demo{
	//方法上的泛型和类的一致,或者说依赖于类的泛型
	public void show(W w){
		System.out.println("show:"+w.toString());
	}
	//不带泛型,不安全。因为在调用方可以把该方法的返回值强转成其它类型,从而出现强转异常
	public Object myprint0(Object a){
		System.out.println("myprint:"+a);
		return a;
	}
	//方法带泛型,但要求和类的泛型相互独立。可以限定返回类型和方法的实参相同,更安全,而且不用强转。
	public  A myprint(A a){
		System.out.println("myprint:"+a);
		return a;
	}
	//静态方法带泛型,泛型一定要独立于类,因为它没有对象。
	public static  A myprint2(A a){
		System.out.println("myprint:"+a);
		return a;
	}	
}


五、Java泛型接口

      这个不好解释直接代码示例了:

interface Inter{
	public abstract V show(V v);
}
//实现泛型接口的类的定义。 方法中的参数类型和类声明实现接口时指定的类型一致,且已经确定为String!-----本例假设我们写这个类的时候知道该类就是专门处理String型数据的
class InterImpl implements Inter{
	@Override
	public String show(String s) {
		System.out.println(s);
		return s;
	}
}
//实现泛型接口的类的定义。 方法中的参数类型和类声明实现接口时指定的类型一致,但不确定!-----本例假设我们写这个类的时候不知道该类是处理什么类型的数据的,但有一点确定:声明类对象时指定什么类型(泛型的实参),show方法就处理该类型
class InterImpl2 implements Inter{
	@Override
	public C show(C s) {
		System.out.println(s);
		return s;
	}
}


六、Java泛型高级

   (PS:关于Java泛型的高级应用,最低要求:虽然自己不一定能写出这样类似的定义,但是你必须会使用或调用(其他程序员或API中已经采用这种技术写的类或方法),所以这里只做最简单的介绍,有兴趣的博友可以去深入学习,博主能力有限,嘿嘿。。)

    1、泛型的通配符:?

             当操作的不同容器中的类型都不确定的时候,而且使用的都是元素从Object类中继承的方法, 这时泛型就用通配符?来表示即可。(助理解的比方: 泛型中的多态应用)

    2、泛型的限定:

            对操作的类型限制在一个范围之内。比如:定义一个功能,只操作Person类型或者Person的子类型。这时可以用:  
                 ? extends E:接收E类型或者E的子类型。这就是上限。 
                 ? super E:   接收E类型或者E的父类型。 这就是下限。

          一般情况下:
                     只要是往容器中添加元素时,使用上限。 ? extends E
                     只要是从容器中取出元素时,是用下限。 ? super E
            高级只有这么多,博友可以去API中看看这种情况,例如:Collection

你可能感兴趣的:(学习日志,Java学习日志)