【Java功能体】快速入门“泛型”

就像是在真实的世界中,用于装每种东西的容器都是不一样的,如装水的叫做水杯、水桶,装煤气的叫做罐子。在集合中,用于装每种数据类型的集合也是不一样的,如String类型必须放在String标记过的集合中而不能放在Integer标记的集合中。在集合中学习泛型,易于理解和接收,本文文将以集合为基础讲解Java语言中泛型机制的用法!

泛型的定义: 为一个集合容器添上一种标记,即指定该集合容器有且只能放哪种类型的数据。

泛型的本质:

  • 是一个数据类型的占位符或者是一个数据类型的变量(类比于C++中的模板)。
  • 一个方法可以接收任意类型的参数,而且返回值类型必须要与实参的类型一致。则是泛型。

泛型的特性:
1,泛型没有多态的概念,左右两边的数据类型必须要一致,或者只是写一边的泛型类型。推荐两边都写泛型。
2,始于JDK1.5
3,将运行时的异常提前至了编译时。
4,避免了无谓的强制类型转换
5,在泛型中不能使用基本数据类型,如果需要使用基本数据类型,那么就使用基本数据类型对应的包装类型

出于规范的目的,Java 还是建议我们用单个大写字母来代表类型参数。常见的如:

  1. T 代表一般的任何类。
  2. E 代表 Element 的意思,或者 Exception 异常的意思。
  3. K 代表 Key 的意思。
  4. V 代表 Value 的意思,通常与 K 一起配合使用。
  5. S 代表 Subtype 的意思

以集合为例,展示泛型的使用方法:

ArrayList<String>  list = new ArrayList<String>();  true     推荐使用。
ArrayList<Object>  list = new ArrayList<String>();  false
ArrayList<String>  list = new ArrayList<Object>();  false

//以下两种写法主要是为了兼顾新老系统的兼用性问题。
ArrayList<String> list = new ArrayList();   true
ArrayList list = new ArrayList<String>();  true   

泛型类

泛型类的定义格式:

class 类名<声明自定义泛型>{
	。。。
}

泛型类要注意的事项:

  1. 在类上自定义泛型的具体数据类型是在使用该类的时候创建对象时候确定的。
  2. 如果一个类在类上已经声明了自定义泛型,如果使用该类创建对象 的时候没有指定 泛型的具体数据类型,那么默认为Object类型
  3. 在类上自定义类的泛型不能作用于静态的方法,如果静态的方法需要使用自定义泛型,那么需要在方法上自己声明使用。(原因:静态的泛型不能引用非静态的泛型)

快速理解泛型类:

class MyArrays<T>{ //定义了泛型:T
	//元素翻转
	public void reverse(T[] arr){ //使用泛型
		for(int startIndex = 0, endIndex = arr.length-1 ; startIndex<endIndex ; startIndex++,endIndex--){
			T temp  = arr[startIndex];
			arr[startIndex] = arr[endIndex];
			arr[endIndex] = temp;
		}
		
	}
	
	public String toString(T[] arr){
		StringBuilder sb = new StringBuilder();
		for(int i = 0 ; i < arr.length ; i++){
			if(i==0){
				sb.append("["+arr[i]+",");
			}else if(i==arr.length-1){
				sb.append(arr[i]+"]");
			}else{
				sb.append(arr[i]+",");
			}
		}
		return sb.toString();
	}
	
	public static <T>void print(T[] t){ //静态的泛型不能引用类泛型,即非静态的泛型
		
	}
}

public class Demo3 {
	public static void main(String[] args) {
		Integer[] arr = {10,12,14,19};
		MyArrays<Integer> tool = new MyArrays<Integer>(); //泛型被确定为Int型;
		tool.reverse(arr);
		System.out.println("数组的元素:"+tool.toString(arr));
		
		MyArrays<String> tool2 = new MyArrays<String>();
		String[] arr2 = {"aaa","bbb","ccc"};
		tool2.reverse(arr2);
				
ArrayList list = new ArrayList ();  //没有指定泛型类型,那它默认为Object类型;
		ArrayList<String> list = new ArrayList<String>();
	}
}

泛型接口

定义格式:

interface 接口名<声明自定义泛型>{
	...
	}

泛型接口要注意的事项:

  1. 接口上自定义的泛型的具体数据类型是在实现一个接口的时候指定的。
  2. 在接口上自定义的泛型如果在实现接口的时候没有指定具体的数据类型,那么默认为Object类型

实现一个还不明确、我目前要操作的数据类型接口的时候,要等待创建接口实现类 对象的时候我才能指定泛型的具体数据类型。

interface Dao<T>{ //接口
	public void add(T t);	
}

class Deo<T> implements Dao<T> {
	public void add(T t){
		//空实现也算实现
	}
}

public class Test {
	public static void main(String[] args) {
		Deo<String> d = new Deo<String>(); //指定该泛型为String类型,上面代码中的T都表示是String类型了
	}
}

泛型方法

方法泛型注意的事项:

  1. 在方法上自定义泛型,这个自定义泛型的具体数据类型是在调用该方法的时候传入实参时确定具体的数据类型的。
  2. 自定义泛型只要符合标识符的命名规则即可, 但是自定义泛型我们一般都习惯使用一个大写字母表示。 T Type E Element

快速理解泛型方法:

public class Demo{

	public static void main(String[] args) {
		String str = getData("abc");  //在调用时依据传入实参才确定泛型的数据类型;
		Integer i = getData(123);  //使用基本数据类型时是使用的其包装类;
	}
	
	public static <T>T getData(T o){  //自定义泛型法则;
		return o;
	}
}

泛型的上下限

诞生背景:
现有以下两个需求,如何才能实现?

  • 需求1: 定义一个函数可以接收任意类型的集合对象,要求接收的集合对象只能存储Integer或者是Integer的父类类型数据。
  • 需求2: 定义一个函数可以接收任意类型的集合对象,要求接收的集合对象只能存储Number或者是Number的子类类型数据。

**泛型中通配符: ? **

  • ? super Integer : 只能存储Integer或者是Integer父类元素。泛型的下限:[Integer, ?]
  • ? extends Number:只能存储Number或者是Number类型的子类数据。泛型上限:[?, Number]

快速理解泛型的上下线:

public static void main(String[] args) {
		ArrayList<Integer> list1 = new ArrayList<Integer>();
		ArrayList<Number> list2 = new ArrayList<Number>();
		
		HashSet<String> set = new HashSet<String>();
		//getData(set);
	}
	//泛型的上限
	public static void getData(Collection<? extends Number> c){ //Number及其子类	

	}

	//泛型的下限
	public static void print(Collection<? super Integer> c){ //Integer及其父类

	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值