黑马程序员之泛型实例

------- android培训java培训、期待与您交流! ----------

泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单

在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的 强制类型转换 ,而这种转换是要求开发者对 实际参数 类型可以预知的情况下进行的。对于 强制类型转换 错误的情况, 编译器 可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
泛型的好处是在编译的时候检查 类型安全 ,并且所有的 强制转换 都是 自动 隐式 的,提高代码的重用率。

通常在集合框架中泛型很常见。在API中有<>的地方,就可以定义泛型。

规则和限制:

1、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
2、同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的 泛型类实例是不兼容的。
3、泛型的类型参数可以有多个。
4、泛型的参数类型可以使用extends语句,例如<T extends superclass>。习惯上称为“有界类型”。
5、泛型的参数类型还可以是 通配符类型。例如Class<?> classType = Class.forName("java.lang.String");

泛型类:

package fighting;

public class GenericClass {

	/**
	 * 泛型类:使用了泛型的类
	 * 
	 * 当类中要操作的引用数据类型不确定的时候,
	 * 早期定义Object来完成扩展
	 * jdk1.5以后定义泛型来完成扩展
	 */
	public static void main(String[] args) {
		//未使用泛型类
		Tool t1 = new Tool();
		//传入的是Worker的实例对象
		t1.setObj(new Worker());
		//传入Worker实例,获取Farmer对象,这样在编译时不会异常,在运行时就会报java.lang.ClassCastException的异常
		Farmer f = (Farmer)t1.getObj();
		System.out.println(f);
		
		//使用泛型类
		Utils<Worker> u1 = new Utils<Worker>();
		u1.setObj(new Worker());
		//泛型优势:不需要使用强制转换类型
		Worker w = u1.getObj();
		//泛型优势:使用了泛型类,则传入Worker实例,获取Farmer对象,在编译时就会报错,这样
//		Farmer f1 =u1.getObj();
//		System.out.println(f1);
		
	}

}

class Worker{
}

class Farmer{
}
//未使用泛型的工具类
class Tool{
	private Object obj;

	public void setObj(Object obj){
		this.obj=obj;
	}
	public Object getObj() {
		return obj;
	}
	
}
//使用了泛型的工具类
class Utils<T>{
	private T obj;
	public void setObj(T obj){
		this.obj = obj;
	}
	
	public T getObj(){
		return obj;
	}
}


泛型方法:

package fighting;

public class GenericMethod {

	/**
	 * 泛型类的局限性:
	 * 泛型类定义的泛型整个类中有效,这个类中所有方法操作的这个类型就固定了.
	 * 如果想实现不同方法操作不同类型,而且类型还不确定,那么可以讲泛型定义在方法上.
	 * 
	 * 泛型方法:相比较泛型类而言,泛型方法更灵活些
	 * 注意:泛型定义在方法上,泛型的定义要在返回值前面
	 * 
	 * 特殊之处:
	 * 静态方法不可以访问类上定义的泛型,如果静态方法操作的引用数据类型不确定,
	 * 可以将泛型定义在方法上
	 * 
	 */
	public static void main(String[] args) {
		
		Demo<String> d = new Demo<String>();
		d.show("haha");
//		d.print(4);//由于泛型类的局限性,这句代码会报异常
		
		Demo2 d2 = new Demo2();
		d2.show("hahahaha");
		d2.show(4);
		d2.print("heihei");
		d2.print(44);
	}

}
//泛型类
class Demo<T>{
	public void show(T t){
		System.out.println("show:"+t);
	}
	public void print(T t){
		System.out.println("print:"+t);
	}
	//静态方法不可以访问类上定义的泛型,如果静态方法操作的引用数据类型不确定,可以将泛型定义在方法上
	public static <W> void method(W w){
		System.out.println("method"+w);
	}
}
//泛型方法
class Demo2{
	public <T> void show(T t){
		System.out.println("show:"+t);
	}
	public <E> void print(E e){
		System.out.println("print:"+e);
	}
}


泛型接口:

package fighting;

public class GenericInterface {

	/**
	 * 泛型接口:
	 * 接口上定义了泛型,在接口的实现类上要指定要操作的数据类型
	 * 如果实现类要操作的数据类型也不确定,可以把实现类定义为泛型
	 */
	public static void main(String[] args) {
		InterImpl i = new InterImpl();
		i.show("ok");
		
		InterImpl2<Integer> i2 = new InterImpl2<Integer>();
		i2.show(22);

		InterImpl2<String> i3 = new InterImpl2<String>();
		i3.show("okok");	
	}

}

interface Inter<T>{
	void show(T t);
}
//这个实现类只能操作String
class InterImpl implements Inter<String>{
	public void show(String t){
		System.out.println("show:"+t);
	}
}

class InterImpl2<T> implements Inter<T>{
	public void show(T t){
		System.out.println("show:"+t);
	}
}


泛型限定:

package fighting;

import java.util.ArrayList;
import java.util.Iterator;

public class GenericLimit {

	/**
	 * 泛型限定:
	 * ?是通配符,也可以理解为占位符
	 * ? extends E:向上限定,可以接受E类型后者E的子类型
	 * ? super E:向下限定,可以接受E类型或者E的父类型
	 */
	public static void main(String[] args) {
		ArrayList<String> a1 = new ArrayList<String>();
		a1.add("abc1");
		a1.add("abc2");
		a1.add("abc3");

		ArrayList<Integer> a12 = new ArrayList<Integer>();
		a12.add(1);
		a12.add(6);
		a12.add(4);
		
		printColl(a1);
		printColl(a12);
		
		//泛型限定
		ArrayList<Person1> al3 = new ArrayList<Person1>();
		al3.add(new Person1("aaa"));
		al3.add(new Person1("bbb"));
		al3.add(new Person1("ccc"));
		
		ArrayList<Student1> al4 = new ArrayList<Student1>();
		al4.add(new Student1("aaa1"));
		al4.add(new Student1("bbb1"));
		al4.add(new Student1("ccc1"));
		//编译异常:相当于ArrayList<Student1> al4= new ArrayList<Person1>(),前后泛型类型不一致
		//printColl2方法中使用泛型限定即可解决
		printColl2(al4);
		

	}
	//?是占位符,这里也可以用T(代表一种数据类型TYPE),两者区别不大
	public static void printColl(ArrayList<?> s1){
		Iterator<?> it = s1.iterator();
		
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
	
	public static void printColl2(ArrayList<? extends Person1> s1){
//		Iterator<Person1> it = s1.iterator();
		Iterator<? extends Person1> it = s1.iterator();
		
		while(it.hasNext()){
			System.out.println(( it.next()).getName());
		}
	}

}

class Person1{
	private String s;
	public Person1(String s){
		this.s=s;
	}
	public String getName(){
		return s;
	}
}

class Student1 extends Person1{
	public Student1(String s){
		super(s);
	}
}


 

两个特殊的小例子:

例1:

/**
 * Map的key和value的组合体用一个特定的类表示,叫Map.Entry
 * 现在要用这个Entry来迭代出每个元素
 */
  HashMap<String,Integer> maps =new HashMap<String,Integer> ();
  maps.put("zxx", 28);
  maps.put("lhm", 35);
  maps.put("fix", 33);
  //Map是不能直接进行迭代的,因为Map没有实现iterable接口
  //要把Map编程Set,Set里面装着每个Entry,然后利用Set进行迭代
  //注意=左边的参数化类型,entrySet()方法的返回值是Set<Map.Entry<K,V>>泛型类型
  Set<Map.Entry<String,Integer>> entrySet  = maps.entrySet();
  for(Map.Entry<String, Integer> entry:entrySet){
   System.out.println(entry.getKey() + ":" + entry.getValue());
  }

 

输出结果:

fix:33
zxx:28
lhm:35

例2:

//交换的方法

 //利用泛型实现交换两个元素的位置
 private static <T> void swap(T[] a,int i,int j){
  T temp = a[i];
  a[i] = a[j];
  a[j]=temp;
 }

//调用交换的方法

 public static void main(String[] args) throws SecurityException, Exception {

  String[] swapStr = new String[]{"abc","xyz","itcast"};
  swap(swapStr,1,2);
  System.out.println(Arrays.asList(swapStr));
  //注意下面这句会编译报错:因为泛型T的实际类型只能是对象类型,不能是基本类型,int是基本类型
//  swap(new int[]{1,2,5,4,5},3,4);
  //想要交换数字可以像下面这样定义成对象类型的
  Integer[] swapInteger = new Integer[]{1,2,5,4,3};
  swap(swapInteger,3,4);
  System.out.println(Arrays.toString(swapInteger));

 }

输出结果:

[abc, itcast, xyz]
[1, 2, 5, 3, 4]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值