设为首页 加入收藏

TOP

泛型的定义、用法与类型通配符的使用方式(二)
2019-09-17 18:52:41 】 浏览:60
Tags:定义 用法 类型 通配符 使用 方式
组,那就还要再次重载代码,如果是八种类型都有,代码量非常庞大。使用泛型方法全部通用,代码如下:

 

	public static void main(String[] args) {
		Integer[] arr =  {1, 8, 15, 6, 3};
		Double[] douArr = {10.5, 25.1, 4.9, 1.8};
		String[] strArr = {"我","是","字","符","串"};
		
		forArrGenric(strArr);
		
	}
	//泛型方法
	public static <T> void forArrGenric(T[] arr) {
		for(int i=0; i < arr.length; i++) {
			System.out.println(arr[i]);
		}
	}
只需定义一个泛型方法,根据运行时传入的参数类型,动态地获取类型,就能做到遍历所有类型数组。但需要注意,泛型的类型参数只能是引用类型,值类型无法在泛型中使用,所以上面的数组都改成了引用类型。值类型需要使用对应的包装类类型。

 

 

 

使用类型通配符

使用之前,先使用常规方式来进行比较。
	public static void main(String[] args) {
		HashSet hs = new HashSet();
		hs.add("A");
		hs.add("QQ");
		hs.add("Alipay");

		new Test2().test2(hs);
	}	
	//普通遍历Set集合,Set是泛型接口,没指定具体泛型参数会引起警告
	public void test(Set s) {
		for(Object o : s)
			System.out.println(o);
	}	
	//增加泛型参数,参数类型是Set<Object>
	public void test2(Set<Object> s) {
		for(Object o : s)
			System.out.println(o);
	}
方法参数的Set集合使用了泛型参数<Object>,方便将参数类型转换成Object,看起来没什么错。当传入一个带泛型参数的集合时,会出现编译错误。代码如下:

 

 

	public static void main(String[] args) {
		HashSet<String> hs = new HashSet();
		hs.add("A");
		hs.add("QQ");
		hs.add("Alipay");
		new Test2().test2(hs); //error
	}	
	//增加泛型参数,参数类型是Set<Object>
	public void test2(Set<Object> s) {
		for(Object o : s)
			System.out.println(o);
	}
因为泛型类不是真正存在的类,所以Set<String>和Set<Object>不存在关系,自然无法作为参数传入进去。这时我们就可以使用类型通配符,如下:

 

 

	//使用类型通配符作为类型参数
	public void test2(Set<?> s) {
		for(Object o : s)
			System.out.println(o);
	}

 

Set<?>表示可以匹配任意的泛型Set。虽然可以使用各种泛型Set了。但弊端就是类型未知,所以无法添加元素。还有范围过于广泛,所以这时可以考虑限制的类型通配符。
 

限制的类型通配符

上面代码只要是泛型Set都允许被遍历,如果只想类型通配符表示一个类和其子类本身呢?设置类型通配符上限,代码如下:

 

 

public class Test2 {
	public static void main(String[] args) {
		ArrayList<Test2> ar = new ArrayList<>();
		List<Test3> lt = new ArrayList<>();
		List<String> lStr = new ArrayList<>();
		demo(ar);
		demo(lt);
		demo(lStr); //error
	}	
	//限制的类型通配符
	public static void demo(List<? extends Test2> t) {
		for(int i = 0; i < t.size(); i++) {
			System.out.println(t.get(i));
		}
	}
}
class Test3 extends Test2{}//子类
<? extends T>:表示类型是T本身或者是T类型的子类类型。

 

<? super T>:表示类型是T类型本身或者是T类型的父类类型。叫做类型通配符的下限。使用方式都差不多。

 

 

 

泛型为何不能应用于静态申明的实例解析

先给一个例子,在静态变量中和静态代码块中使用泛型。
public class Test<T> {
	public static T name;  //error
	public T sex ;
	
	static {
		T ab; //error
	}
}
报出异常:不能使一个静态引用指向一个非静态的类型 T。静态和非静态之分就在于静态是编译时类型,动态是运行时类型。T代表未知类型,如果可以用于静态申明,因为是未知类型,系统没法指定初始值,手动赋值也不行,因为不知道啥类型,只有运行时才可以指定。而泛型存在的意义就是为了动态指定具体类型,增强灵活性和通用性,所以用于静态声明违背了使用原则。为什么实例变量和实例方法可以使用呢?因为当你使用实例变量或者方法时,就说明对象存在了,即代表泛型参数也指定了。未指定具体类型默认是Object类型。
 

为什么静态方法中可以定义泛型方法呢?

先给三个实例,我们来慢慢分析。
public class Test<T> {
	public static void main(String[] args) {
		
	}
	
	//泛型方法
	public T demo1(T t) {
		return t;
	}
	
	//静态方法使用泛型参数
//	public static T demo2(T t) { return t;}
				
	//定义泛型静态方法
首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇上云之路之企业级云上网络解决方案 下一篇如何拆分微服务架构?

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目