java 自定义泛型

Java泛型编程是JDK1.5版本后引入的!

一.泛型的优点

(1)类型安全

    通过知道使用泛型定义的变量的类型限制,编译器可以更有效地提高Java程序的类型安全。 

(2)消除强制类型转换 

    消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。所有的强制转换都是自动和隐式的。

(3)提高性能。 

    在泛型的实现中,编译器将强制类型转换插入生成的字节码中,但是更多类型信息可用于编译器这一事实,为未来版本的 JVM 的优化带来了可能。

二.泛型使用的注意事项

 (1)泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。

(2)泛型的类型参数可以有多个。

(3)不能对确切的泛型类型使用instanceof操作。如下面的操作是非法的,编译时会出错。

  1. if(ex_num instanceof FX<Number>){   
  2. }  
  (4)不能创建一个确切的泛型类型的数组。下面使用 Sun 的一篇文档 的一个例子来说明这个问题:

  1. List<String>[] aa = new List<String>[5]; // Not really allowed.    
  2. Object o = aa;    
  3. Object[] oa = (Object[]) o;    
  4. List<Integer> li = new ArrayList<Integer>();    
  5. li.add(new Integer(3));    
  6. oa[1] = li; // Unsound, but passes run time store check    
  7. String s = lsa[1].get(0); // Run-time error: ClassCastException.    

这种情况下,由于JVM泛型的擦除机制,在运行时JVM是不知道泛型信息的,所以可以给oa[1]赋上一个ArrayList<Integer>而不会出现异常,但是在取出数据的时候却要做一次类型转换,所以就会出现ClassCastException,如果可以进行泛型数组的声明,上面说的这种情况在编译期将不会出现任何的警告和错误,只有在运行时才会出错。

下面采用通配符的方式是被允许的:

    1. List<?>[] aa= new List<?>[5]; // OK, array of unbounded wildcard type.    
    2. Object o = aa;    
    3. Object[] oa = (Object[]) o;    
    4. List<Integer> li = new ArrayList<Integer>();    
    5. li.add(new Integer(3));    
    6. oa[1] = li; // Correct.    
    7. Integer i = (Integer) lsa[1].get(0); // OK  

三.自定义泛型

3.1 泛型类 T

import java.util.List;
/**
 * 泛型类
 * @author Administrator
 *
 * @param <T>
 */
//我们常见的如T、E、K、V等形式的参数常用于表示泛型形参,由于接收来自外部使用时候传入的类型实参。
public class Student<T> { //T代表是任意类型!
	private T data;   //data类型由T指定[即:由外部指定  ]

	public T getData() {  //返回值的类型由外部决定 
		return data;
	}

	public void setData(T data) {// 设置的类型也由外部决定  
		this.data = data;
	}

	/**
	 * 构造方法
	 * @param data
	 */
	public Student(T data) {
		super();
		this.data = data;
	}

	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}
	
	
	
}
测试类

public class TestStudent {

	public static void main(String[] args) {
		Student<String> stu = new Student<String>();// data类型为String类型
		stu.setData("mike"); // 设置字符串
		System.out.println(stu.getData().length()); // 获得字符串长度

//		method_1();
		
//		method_2();
		
		method_3();

	}
	
	
	private static void method_3() {
		//类型通配符
		Student<String> ints = new Student<String>("QQ");
		Student<Object> floats = new Student<Object>(new Date());
        getData3(ints);
        getData3(floats);  
	}
	private static void method_2() {
		//类型通配符
		Student<Number> ints = new Student<Number>(10);
		Student<Float> floats = new Student<Float>(20.5f);
		getData2(ints);
		getData2(floats);  
	}

	private static void method_1() {
		//类型通配符
		Student<Number> ints = new Student<Number>(10);
		Student<Float> floats = new Student<Float>(20.5f);
        getData1(ints);
       // getData1(floats);  //发生异常
	}

	public static void getData1(Student<Number> data) {//只能接收Number
		System.out.println("data :" + data.getData());
	}
	
	public static void getData2(Student<? extends Number> data) {//只能接收Number及其Number的子类  
		System.out.println("data :" + data.getData());
	}
	
	public static void getData3(Student<? super String> data) {// 只能接收String或Object类型的泛型  
		System.out.println("data :" + data.getData());
	}

}

注意:<T extends Number> 表示 T 只接受 Number 及其子类,传入其他类型的数据会报错。这里的限定使用关键字 extends,后面可以是类也可以是接口。但这里的 extends 已经不是继承的含义了,应该理解为 T 是继承自 Number 类的类型,或者 T 是实现了 XX 接口的类型。

3.2 泛型类 <K,V>
/**
 * 泛型类
 * @author Administrator
 *
 * @param <K>
 * @param <V>
 */
public class City<K, V> {  //指定了两个泛型类型  
	private K key;    //key类型由外部决定  
	private V value;  //value类型由外部决定  

	public K getKey() {
		return key;
	}

	public void setKey(K key) {
		this.key = key;
	}

	public V getValue() {
		return value;
	}

	public void setValue(V value) {
		this.value = value;
	}

	public City(K key, V value) {
		super();
		this.key = key;
		this.value = value;
	}

	public City() {
		super();
		// TODO Auto-generated constructor stub
	}

}
测试类
public static void main(String[] args) {
		// key-value
		City<String, Integer> city = new City<String, Integer>("John", 20);
		System.out.println(city.getKey() + ":" + city.getValue());

	}


3.3 泛型接口

/**
 * 泛型接口
 * 
 * @author Administrator
 * 
 * @param <T>
 */
public interface Animal<T> {
	T eat(); // 抽象方法返回值就是泛型类型
}

/**
 * 定义泛型接口的子类
 * 
 * @author Administrator
 * 
 * @param <T>
 */
class Cat<T> implements Animal<T> {

	private T property; // 定义属性

	public T getProperty() {
		return property;
	}

	public void setProperty(T property) {
		this.property = property;
	}

	/**
	 *  通过构造方法设置属性内容  
	 * @param property
	 */
	public Cat(T property) {
		super();
		this.property = property;
	}

	/**
	 * 重写这个方法
	 */
	@Override
	public T eat() {
		// TODO Auto-generated method stub
		return this.property;
	}

}
测试类

public static void main(String[] args) {
		Cat<String> cat = new Cat<String>("加菲猫");
		System.out.println(cat.eat() + "~~~吃鱼!");
	}

3.4 泛型方法

/**
 * 泛型方法
 * 
 * @author Administrator
 * 
 */
public class Bear {
	public <T> T get(T t) { // 可以接收任意类型的数据
		return t;

	}
	
	
	public static void main(String[] args) {
		Bear bear = new Bear();
		//T :接收任意类型的数据  
		System.out.println(bear.get("大白熊")); //字符串
		System.out.println(bear.get(100.56)); //浮点型
		System.out.println(bear.get(true)); //布尔型
	}
}
3.5 泛型数组
public static void main(String[] args) {
		// 声明数组
		Integer arr[] = add1(11, 22, 33, 44, 55);
		
		add2(arr);
	}

	public static <T> T[] add1(T... arg) { // 接收可变参数
		return arg; // 返回泛型数组
	}

	public static <T> void add2(T...arg) { // 接收可变参数
		System.out.print("接收泛型数组:");
		for (T t : arg) {
			System.out.print(t + "\t");
		}
		System.out.println();
	}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值