泛型 Generic

 泛型的本质:类型参数化

一:泛型的优点:
    a, 让我们少写几个类的代码,b,让我们定义安全的泛型类

二:自定义泛型类:

package gen01;
/**
 * 自定义泛型类    BasicController
 * @author john
 *
 * @param <E>
 * @param <S>
 */
public class BasicController<E,S> {
	private E e;
	//private static S s; //泛型不能定义在静态属性上
	
	public BasicController() {
		super();	
	}
}

 

三:自定义泛型接口:

package gen01;
/**
 * 泛型接口  Comparator
 * @author john
 *
 * @param <E>
 */
public interface Comparator<E> {
	//接口不能有泛型属性,因为接口的属性是静态的。
	// /*public static final*/ E e;
	
	//公共的抽象方法
	/*public abstract */ E compare(E e);
}

 

四:自定义泛型方法:

package gen01;

import java.io.Closeable;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * 非泛型类中定义泛型方法
 * @author john
 *
 */
public class Method {
	//自定义泛型方法   
	//定义:  在返回类型前加上<字母>
	public static <T> void test(T t){
		System.out.println(t);
	}
	
	//自定义释放资源的泛型方法
	public static <T extends Closeable> void testClose(T... t){
		for(T temp:t){
			try {
				if(null!=temp){
					temp.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) throws FileNotFoundException {
		test("自定义泛型方法测试");
		testClose(new FileInputStream("G:\\aaa.txt"));
	}
}

 

五:父类为泛型类,子类继承时:

    子类为富二代

package gen02;
/**
 * 泛型父类
 *1,保留父类泛型,子类必须为泛型。
 *2,不保留父类泛型,子类按需实现。
 *
 *属性及方法类型随位置而定
 *子类重写方法类型    --->随父类而定
 *eg: test 方法的参数
 *子类使用父类的属性  --->随父类而定
 *eg: this.age;
 *
 *子类中使用自己的属性 --->随自己而定
 *eg: Child1中的 A sex;
 *
 * @author john
 *
 * @param <T1>
 * @param <T2>
 */
public abstract class Father<T1,T2>{
	T1 age;
	public abstract void test(T2 name);
}

//保留
//1,全部保留
class Child1<T1,T2,A> extends Father<T1,T2>{
	A sex;
	
	@Override
	public void test(T2 name) {
		T1 t1 = this.age; //---> T1
	}
}

//2,部分保留
class Child2<T2,A> extends Father<Integer,T2>{

	@Override
	public void test(T2 name) {
		Integer tempAge = this.age; //--->Integer
	}}

//不保留
//1,有具体类型
class Child3 extends Father<Integer,String>{
	@Override
	public void test(String name) {
		Integer tempAge = this.age; //--->Integer
	}
}

//2,没有具体类型 ,擦除
class Child4 extends Father{

	@Override
	public void test(Object name) {
		Object tempAge = this.age; //--->Object
	}
}

//Child4 等价于  class Child5 extends Father<Object,Object>{}

六:接口为泛型接口 实现类实现时:

同上 

 

七:泛型擦除:

泛型擦除指使用|实现|继承的时候没有指定类型,我们称之为泛型擦除。

类似于Object, 不完全等同于Object   不指定类型编译不会自动检查,指定类型后编译会自动检查

package gen02;
/**
 * 泛型擦除
 * 泛型擦除指使用|实现|继承的时候没有指定类型
 * 类似于Object, 不完全等同于Object  不指定类型编译不会自动检查,指定类型后编译会自动检查
 * 
 * @author john
 */
public class MyStuApp {

	public static void main(String[] args) {
		MyStudent myStudent = new MyStudent<>();
		myStudent.setAge(18);
		Object age = myStudent.getAge();
		
		test(myStudent);//不指定类型编译不会自动检查
		
		MyStudent<Object> myStudent2 = new MyStudent<Object>();
		//test(myStudent2);//指定类型后编译会自动检查,此处会报错
	}
	
	public static void test(MyStudent<String> student){
		System.out.println(student.getAge());
	}
}

class MyStudent<T>{
	T age;
	public T getAge() {
		return age;
	}
	public void setAge(T age) {
		this.age = age;
	}
}

 八:泛型通配符"?":

表示类型不确定,只能用在声明变量,不能用在定义泛型类、泛型接口、泛型方法上。

 

package gen03;

import java.util.ArrayList;
import java.util.List;

public class WildcardTest {

	public static void main(String[] args) {
		//声明
		List<?> lists = new ArrayList<String>();	
		lists = new ArrayList<Integer>();
		lists = new ArrayList<Object>();
		
		//编译错误  通配符不能用来创建对象
		//lists = new ArrayList<?>();
	}
	
	public static void test(List<?> lists){
		
	}
	
	//不能用在创建泛型方法   编译通不过
//	public static <?> void test2(List<?> lists){
//		
//	}
}

//不能用在创建泛型类   编译通不过
//class Test<?>{
//	
//}

 

 

九:泛型上限"extends":

一般用于限制操作,表示小于等于,即子类或自身。

不能添加数据进去的理由是:保证向下兼容一致性。

 

package gen03;
/**
 * 继承链
 *      Object
 *        |
 *      Fruit
 *      /  \
 *   Apple Pear
 *     |
 *   FujiApple
 *   
 * @author john
 *
 */
public class Fruit {}

class Apple extends Fruit{};

class Pear extends Fruit{};

class FujiApple extends Apple{};

 

package gen03;

import java.util.ArrayList;
import java.util.List;
/**
 * extends 泛型上限  <=  即子类
 * 1,一般使用于限制操作。
 * 2,不能使用在添加数据操作     保证向下兼容一致性。
 * 3,规则
 * 
 * @author john
 */
public class ExtendsTest {

	public static void main(String[] args) {
		//extends 为上限
		//1 泛型定义属性
		Test<Fruit> test1 = new Test<Fruit>();
		Test<Pear> test2 = new Test<Pear>();
		Test<Apple> test3 = new Test<Apple>();
		
		//泛型没有多态     下面这行代码编译无法通过
//		Test<Apple> test4 = new Test<FujiApple>();
		
		List<? extends Fruit> list1 = new ArrayList<Fruit>();
		test(list1);
		
		List<Fruit> list2 = new ArrayList<Fruit>();
		test(list2);
		
		List<Apple> list3 = new ArrayList<Apple>();
		test(list3);
		
		List<? extends Apple> list4 = new ArrayList<FujiApple>();
		test(list4);
		
		//?  -->为什么报错  因为? 等同于 ? extends Object  Object>Fruit 所以报错
		List<?> list5 = new ArrayList<FujiApple>();
		//test(list5);
		
	}
	
	//2 使用extends定义泛型方法    ? extends Fruit
	public static void test(List<? extends Fruit> lists){
		//lists 不能添加任何非空对象 进去的理由是:保证向下兼容一致性。
//		lists.add(new Fruit());
//		lists.add(new Apple());
//		lists.add(new Pear());
//		lists.add(new FujiApple());
//		lists.add(null);
	}
	
	//泛型类
	static class Test<T extends Fruit>{}
}

 

十:泛型下限"super":

 一般用于限制操作,表示大于等于,即父类或自身。

不用用来添加父类数据进去的理由是:保证向上兼容一致性。

 

package gen03;
/**
 * 继承链
 *      Object
 *        |
 *      Fruit
 *      /  \
 *   Apple Pear
 *     |
 *   FujiApple
 *   
 * @author john
 *
 */
public class Fruit {}

class Apple extends Fruit{};

class Pear extends Fruit{};

class FujiApple extends Apple{};

 

package gen03;

import java.util.ArrayList;
import java.util.List;
/**
 * extends 泛型下限  >=   即父类或自身。
 * @author john
 */
public class SuperTest {

	public static void main(String[] args) {
		List<Fruit> list1 = new ArrayList<Fruit>();
		test(list1);
		
		List<Object> list2 = new ArrayList<Object>();
		test(list2);
		
		List<Apple> list3 = new ArrayList<Apple>();
		test(list3);
		
		List<? extends Apple> list4 = new ArrayList<Apple>();
		//test(list4); //编译通不过
	}
	
	// 使用extends定义泛型方法
	public static void test(List<? super Apple> lists){
		//自能添加自身或者子对对象    不能添加父类对象     理由是:保证向上兼容一致性。
		lists.add(new Apple());
		lists.add(new FujiApple());
		//lists.add(new Fruit());//编译通不过
	}
}

 

十一:泛型嵌套:

package gen03;
/**
 * 泛型嵌套
 * @author john
 *
 */
public class GenericQianTao {
	public static void main(String[] args) {
		Student<Integer> student = new Student<Integer>();
		student.setScore(100);
		Class<Student<Integer>> bj = new Class<Student<Integer>>();
		bj.setStudent(student);
		
		Student<Integer> stu = bj.getStudent();
		System.out.println(stu.getScore());
	}
}

class Student<T>{
	T score;

	public T getScore() {
		return score;
	}

	public void setScore(T score) {
		this.score = score;
	}
}

class Class<T>{
	T student;

	public T getStudent() {
		return student;
	}

	public void setStudent(T student) {
		this.student = student;
	}
} 

 

JDK里面嵌套的典型应用是Map集合遍历时使用Entry时的场景。

 

 

泛型没有多态。

没有泛型数组。

jdk1.7对泛型的简化 List<String> lists = new ArrayList<>();

 

 

后面的有时间整理下  20160509。

 

二: 定义泛型:
    a,定义单个类型持有者  UserDao<User>  userDao = new UserDao<User>();
    b,定义多个类型持有者  UserDao<Long,User>  userDao = new UserDao<Long,User>();

三:限制泛型的可用类型(有界类型 extends  super):
 1, extends
    a,定义类/接口
    public class UserDao<T>{
        ...
    }
    与
    public class UserDao<T extends Object>{
        ...
    }
    是等价的。
    
    所以我们想用限制类型定义类的时候该写成   注意1:不能用将T换成?  程序会报错。可以定义多个类型持有者。

    public class UD<T extends Fruit>{
        .... 

    }

    注意2:public   class/interface  父类/父接口名字<T>  
      或者  public   class/interface   类/ 接口名字<E extends BasicEntity> 
     的子类/子接口/实现类  在继承父类/继承父接口i/实现接口中   
     写法最好是   public  class/interface  子
类/子 接口名字   extends/implements   类/ 接口名字<User>   
                 或者  
public  class/interface  子 类/子 接口名字<E extends BasicTreeEntity>   extends/implements   类/ 接口名字<E>

 
    b,定义变量     这里不理解为什么会报错   既然报错这种定义会有什么用处呢?

 

List<? extends Fruit> list1 = new ArrayList<Fruit>();

List<? extends Fruit> list2 = new ArrayList<Apple>();

List<? extends Fruit> list3 = new ArrayList<Orange>();

//list1.add(new Fruit()); // 报错

//list2.add(new Apple()); // 报错

  //list3.add(new Orange()); // 报错

    //list2  list3
//其实编译器根据 ? extends Fruit 只知道:list中可以是Fruit或它的任何某种子类型对象,但具体是什么类型是不确定的,
//所以你add(new Fruit()); add(new Orange()); add(new Apple()); 编译器都是会报错的;
//
//如果难理解,反过来理解:
//比如fruits.add(new Orange()),这里是add一个Orange类型对象,
//而fruits要求add的对象类型必须是Fruit或它的任何某种子类型对象,
//这个某种类型能用Orange或Fruit或Apple来表示吗?    

//另外一种解释     http://blog.csdn.net/hippoppower/article/details/4473991


    c,方法参数  和  返回值类型     理解这种代码的写法     以后自己写代码多用这种.  
    定义父类型   传参的时候可以传递父类和父类的子类进去。返回实际类型。

public static   List<? extends Fruit>  sortTreeList( List<? extends Fruit> list){
return list;
}
        
调用上面的方法的代码
List<Fruit> fruitList = new ArrayList<Fruit>();
fruitList.add(new Apple());
fruitList.add(new Orange());
sortTreeList(fruitList);
 或者
List<Apple> appleList = new ArrayList<Apple>();
appleList.add(new Apple());
sortTreeList(appleList);
 
 
  2,super
    a,定义类     没有这种写法

    b,定义变量       不理解这里      也不理解这种定义的用处。
List<? super Fruit> list4 = new ArrayList<Fruit>();
//List<? super Fruit> list5 = new ArrayList<Apple>();  // 报错
//List<? super Fruit> list6 = new ArrayList<Orange>(); // 报错
list4.add(new Apple());
list4.add(new Orange());
list4.add(new Fruit()); 
 
    c,定义方法和返回参数    理解这种代码的写法   但是不知道这种写法有什么适用场景。
    
public static   List<? super Apple>  sortTreeList2( List<? super Apple> list){
return list;
}
        调用上面的方法的代码
   List<Fruit> fruitList2 = new ArrayList<Fruit>();
fruitList2.add(new Apple());
fruitList2.add(new Orange());
sortTreeList2(fruitList);
        或者 
List<Apple> appleList2 = new ArrayList<Apple>();
appleList2.add(new Apple());
sortTreeList2(appleList);       



    
 

 

 

猜你喜欢

转载自wangshirufeng.iteye.com/blog/2244798