泛型

泛型(generic)的作用就是通过一次编码来操作不同类型的数据。编写代码时,可以定义一个代码“模板”,其中的数据类型使用泛型标识,这样有就效地简化了代码编写工作。当代码编译时,会将类型标识绑定为实际数据类型,这样就保证了代码的执行效率。

在类、方法、接口等结构中都可以使用泛型,下面分别讨论。

泛型类

在JDK中,已经将大量的资源改写为泛型类型,如下面的代码演示了ArrayList类的应用。

Java
import java.util.ArrayList;
public class Hello {
	public static void main(String[] args){
		ArrayList<String> lst = new ArrayList<String>();
		lst.add("abc");
		lst.add("def");
		lst.add("ghi");
		for(String s :lst)
			System.out.println(s);
	}
}

代码执行结果如下图。

本例,通过<>符号指定ArrayList中的成员为字符串类型(String),然后,通过对象的add()方法添加了三个成员,最后,通过for循环显示所有成员内容。

自定义类中,同样可以使用泛型,如下面的代码。

Java
public class CDictItem<K, V> {
	public K key;
	public V value;
	// 构造方法
	public CDictItem(K k, V v) {
		key = k;
		value = v;
	}
}

代码中,在CDictItem类中使用了两个泛型标识,分别是K和V;下面的代码,我们在main()方法中测试CDictItem类的使用。

Java
public class Hello {
	public static void main(String[] args){
		CDictItem<String, String> item1 = new CDictItem<String,String>("mars","火星");
		System.out.printf("%s : %s \n", item1.key, item1.value);
		//
		CDictItem<Integer, String> item2 = new CDictItem<Integer, String>(1,"金星");
		System.out.printf("%d : %s", item2.key, item2.value);
	}
}

请注意item2对象,它使用的类型是CDictItem<Integer,String>,这里的整数使用了基本数据类型的包装类,而不是直接使用int类型。代码执行结果如下图。

泛型方法

在方法中同样可以使用泛型,如下面的代码,我们通过inList()方法判断一个值是否存在于一个数据集合中。

Java
public class Hello {
	public static void main(String[] args){
		System.out.println(inList(1,1,2,3));
		System.out.println(inList("a","b","c","d"));
	}
	@SafeVarargs
	public static <T> boolean inList(T x, T...lst) {
		for(T item : lst) {
			if(x==item) return true;
		}
		return false;
	}
}

代码执行结果如下图。

本例,我们定义了inList()泛型方法,请注意泛型标识定义的位置在方法返回值类型之前;定义泛型标识后,就可以在返回值类型、参数和方法体中使用。inList()方法的功能是判断参数1的值是否在从第二个参数开发的数据列表中。

泛型接口

泛型接口与泛型方法的定义比较相似,只是泛型接口最终还是需要使用泛型类来实现,如下面的代码,我们定义了IDictItem接口。

Java
public interface IDictItem<K, V> {
	public K getKey();
	public void setKey(K k);
	public V getVvalue();
	public void setValue(V v);
}

那么,使用CDictItem类实现IDictItem接口的实现就如下面的代码。

Java
public class CDictItem<K, V> implements IDictItem<K, V>{
	public K key;
	public V value;
	// 构造方法
	public CDictItem(K k, V v) 
	{
		key = k;
		value = v;
	}
	// 实现IDictItem接口
	public K getKey() 
	{
		return key;
	}
	public void setKey(K k) 
	{
		key=k;
	}
	public V getValue() 
	{
		return value;
	}
	public void setValue(V v) 
	{
		value=v;
	}
}

下面的代码,我们使用IDictItem定义CDictItem对象。

Java
public class Hello {
	public static void main(String[] args){
		IDictItem<String,String> item = 
				new CDictItem<String,String>("Earth","地球");
		System.out.printf("%s : %s",
				item.getKey(),item.getValue());
	}
}

这里将item对象声明为IDictItem接口类型,也意味着它不能使用CDictItem类中的key和value对象来保存和读取数据,而只能使用IDictItem接口中定义的方法。代码执行结果如下图。

泛型约束

泛型约束,又称为泛型限制,其功能指定泛型中数据类型的允许范围,其主要包括:

  • <T extends 类或接口>,指定T类型只能使用指定的类或接口类型。
  • <T extends 类或接口 & 类或接口>,指定T类型可以使用多个指定的类或接口类型。
  • <? extends 类>,指定泛型类型可以使用指定类及其子类。
  • <? super 类>,指定泛型类型可以使用指定类及其超类。

下面的代码演示了泛型约束的应用。

Java
public class C4<T extends I3> {
	public T i3obj;
	public void method4() {
		i3obj.method1();
		i3obj.method2();
		i3obj.method9();
		System.out.println("method4 is working");
	}
}

本例中定义的C4类中,泛型类型只能使用实现了I3接口的类型,其中的method4()方法中调用了I3接口中的method1()、method2()和method9()方法。下面,我们在main()方法中C4类的相关应用。

Java
public class Hello {
	public static void main(String[] args){
		I3 c3 = new C3();
		C4 c4 = new C4();
		c4.i3obj = c3;
		c4.method4();
	}
}

代码执行结果如下图。

如果将代码中c4对象的i3obj属性设置为没有实现I3接口的对象,代码是不能执行的,如下面的代码。

Java
public class Hello {
	public static void main(String[] args){
		C4 c4 = new C4();
		c4.i3obj = new CAuto();
		c4.method4();
	}
}

代码执行结果如下图。

本站内容均为原创作品,转载请注明出处,本页面网址为:http://caohuayu.com/chy/article/Article.aspx?code=cc001010