Java基础知识之泛型以及自定义泛型

铁子们,快扫码关注啦!或 wx搜索:“聊5毛钱的java”,关注可领取博主的Java学习视频+资料,保证都是通俗易懂的干货

之前的文章讲过了:

反射---用最直接的大白话来聊一聊Java中的反射机制

内省---Java反射——内省(Introspector)以及BeanUtils内省框架

枚举---用最直接的大白话聊一聊,Java中的枚举类你真的理解了吗

注解和自定义注解---Java中的注解以及自定义注解

接下来,本篇讲一下泛型

一、什么是泛型和泛型的作用

首先要明白的一点是:泛型是为了安全方面的考虑,泛型可以把运行时期的问题,提前暴露在编译期

JDK5以前,对象保存到集合中就会失去其特性,取出时通常要程序员手工进行类型的强制转换

这样不可避免就会引发程序的一些安全性问题。

例如:下面的代码,编译可以通过,运行时才会报错,在编译时发现不了错误

ArrayList list = new ArrayList();
list.add("abc");
Integer num = (Integer) list.get(0);  //运行时才会报错,在编译时发现不了

再例如:在遍历集合的时候,无法遍历,因为放入集合中的数据类型是不确定的

List list = new ArrayList();
//放入集合一个int型的
list.add(1);
//放入集合一个String类型的
list.add("fuck");

所以JDK5以后出现了泛型,泛型允许程序员在编写集合代码时就限制集合的处理类型,从而把原来程序运行时可能发生问题,转变为编译时的问题,以此提高程序的可读性和稳定性。

***注意:泛型是提供给javac编译器使用的,它用于限定集合的输入类型,让编译器在源代码级别上,即挡住向集合中插入非法数据。但编译器编译完带有泛型的java程序后,生成的class文件中将不再带有泛型信息,以此使程序运行效率不受到影响,这个过程称之为“擦除”

二、泛型的典型应用

(1)使用增强for循环迭代泛型集合中的元素。

    @Test//泛型遍历List集合
	public void test2(){
		List<String> list = new ArrayList<String>();
		list.add("u");
		list.add("fuck");
		for(String s:list){
			System.out.println(s);
		}
	}

(2)存取HashMap中的元素。

    @Test//泛型遍历Map,方式一
	public void test3(){
		Map<Integer, String> map = new LinkedHashMap<Integer, String>();
		map.put(1, "aaa");
		map.put(2, "bbb");
		map.put(3, "ccc");
		
		Set<Integer> keys = map.keySet();
		for(Integer i:keys){
			String value = map.get(i);
			System.out.println("key:"+i+"\tvalue:"+value);
		}
		
	}
	
	@Test//泛型遍历Map,方式二
	public void test4(){
		Map<String, String> map = new LinkedHashMap<String, String>();
		map.put("a", "aaa");
		map.put("b", "bbb");
		map.put("c", "ccc");
		
		Set<Map.Entry<String, String>> set = map.entrySet();//Set中的元素是Map.Entry类型的
		for(Map.Entry<String, String> me:set){
			String key = me.getKey();
			String value = me.getValue();
			System.out.println("key:"+key+"\tvalue:"+value);
		}
	}

使用泛型时的几个常见问题:

a、使用泛型时,泛型类型须为引用类型,不能是基本数据类型

b、如果等号左右两边都用到了泛型,则泛型里的类型必须一模一样。如以下的两种就不行

ArrayList<String> list = new ArrayList<Object>();

ArrayList<Object> list = new ArrayList<String>(); 

c、只有一边使用泛型,另一边不使用泛型是允许的。如下边的两种形式是可以的

ArrayList<String> list = new ArrayList ();

ArrayList list = new ArrayList<String>();

这么做的目的是为了兼容

举个例子

    @Test
	public void test5(){
		//JDK1.5以后的新时代程序员调老程序员写的东西
		List<String> list = getList();
		
		//一个老程序员调用新程序员写的东西
		List li = getAnthorList();
	}
	
	//一个老程序员写的方法如下
	public List getList(){
		return null;
	}

	//一个新时代程序员写的方法如下
	public List<String> getAnthorList(){
		return null;
	}

三、自定义泛型的语法

想使用泛型,就需要先定义泛型,泛型有两种定义的方式:

1、在方法上定义,写在返回值之前

Java程序中的普通方法、构造方法和静态方法中都可以使用泛型。

方法使用泛型前,必须对泛型进行声明,语法:<T> ,T可以是任意字母,但通常必须要大写。一般情况下大写是类型,小写是参数。

<T>需放在方法的返回值声明之前。

public class Demo2 {

    //无返回值
	public <T>  void m1(T t){
		
	}

    //有返回值的实例方法
	public <T> T m2(T t){
		return t;
	}

    //有返回值的静态方法
	public static <T> T m3(T t){
		return t;
	}
	
}

2、在类上定义,写在类名之后

除了在方法上声明泛型之外,还可以在类上声明泛型

但是需要注意的是:在类上面声明泛型,仅限于实例方法上直接使用,但是不适合静态方法,静态方法上的泛型还是需要在方法上单独定义的

例如:

//在类上面声明泛型,在实例方法上直接用即可;但是不适合静态方法
//静态方法上使用的泛型声明必须单独定义
public class Demo2<T> {

	public void m1(T t){
		
	}

	public T m2(T t){
		return t;
	}
	
}

上边就是泛型的基本语法和使用

四、使用泛型练习几个案例

(1)编写一个泛型方法,实现数组元素的交换。

//自定义泛型练习
public class GenericUtil {
	//颠倒任意数组中的指定位置上的两个元素
	//比如[1,2,3]   颠倒0和2位置上的元素   [3,2,1]
	public static <T> void m1(T[] t,int index1,int index2){
		//临时变量
		T temp = t[index1];
		t[index1] = t[index2];
		t[index2] = temp;
	}
}
public class Demo3 {
	@Test
	public void test1(){
		String s1[] = {"a","b","c"};
		GenericUtil.m1(s1, 1, 2);
		List list = Arrays.asList(s1);
		System.out.println(list);
		
	}
}

最后输出结果为 a,c,b

(2)编写一个泛型方法,接收一个任意数组,并颠倒数组中的所有元素。

//自定义泛型练习
public class GenericUtil {
	//颠倒任意类型数组中的元素顺序
	//[1,2,3]  [3,2,1]
	public static <T> void reverse(T[] t){
		int startIndex = 0;
		int endIndex = t.length -1;
		while(startIndex<endIndex){
			T temp = t[startIndex];
			t[startIndex] = t[endIndex];
			t[endIndex] = temp;
			startIndex++;
			endIndex--;
		}
	}
}
public class Demo3 {
	@Test
	public void test2(){
		String s1[] = {"a","b","c"};
		GenericUtil.reverse(s1);
		List list = Arrays.asList(s1);
		System.out.println(list);//输出结果为c,b,a
		
		Integer ii[] = {1,2,3};
		GenericUtil.reverse(ii);//注意:只有引用类型才能作为泛型方法的实际参数
		list = Arrays.asList(ii);
		System.out.println(list);//输出结果为3,2,1
	}
}

以上就是对泛型的一些学习和总结,如有不正确的地方,可以在评论区进行指正,一起学习一起进步,谢谢

铁子们,如果觉得文章对你有所帮助,可以点关注,点赞

也可以关注下公众号:扫码或 wx搜索:“聊5毛钱的java”,欢迎一起学习交流,关注公众号可领取博主的Java学习视频+资料,保证都是干货

3Q~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

曹举的个人博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值