JavaSE 泛型

一、泛型概述

  • 泛型是JDK5之后的新特性,泛型,即“参数化类型”,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用传入具体的类型(类型实参)
  • 泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型),也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法
  • 泛型只在编译阶段有效,在编译之后程序会采取去泛型化的措施,即在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出(可以使用桥接解决),并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法,所以泛型不会进入到运行时阶段

二、使用与不使用泛型区别

  • 不使用泛型
public class Test {
	public static void main(String[] args) {
		/**
		 * 不使用泛型机制,分析程序存在缺点
		 */
		List myList = new ArrayList();

		// 准备对象
		Cat c = new Cat();
		Bird b = new Bird();

		// 将对象添加到集合当中
		myList.add(c);
		myList.add(b);

		// 遍历集合,取出每个Animal,让它move
		Iterator it = myList.iterator();
		while (it.hasNext()) {
			Object obj = it.next();
			// obj中没有move方法,无法调用,需要向下转型
			if (obj instanceof Animal) {
				Animal a = (Animal) obj;
				a.move();
			}
		}
	}
}

class Animal {
	// 父类自带方法
	public void move() {
		System.out.println("Animal move");
	}
}

class Cat extends Animal {
	// 特有方法
	public void catchMouse() {
		System.out.println("Cat move");
	}
}

class Bird extends Animal {
	// 特有方法
	public void fly() {
		System.out.println("Bird move");
	}
}
  • 使用泛型
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Test {
	public static void main(String[] args) {
		/**
		 * 使用泛型机制
		 */
		// 使用泛型List<Animal>之后,表示List集合中只允许存储Animal类型的数据
        // 用泛型来指定集合中存储的数据类型
        List<Animal> myList = new ArrayList<Animal>();

        // 指定List集合中只能存储Animal,那么存储String就编译报错了
        // 这样用了泛型之后,集合中元素的数据类型更加统一了
        //myList.add("a");

        Cat c = new Cat();
        Bird b = new Bird();

        myList.add(c);
        myList.add(b);

        // 获取迭代器
        // 这个表示迭代器迭代的是Animal类型
        Iterator<Animal> it = myList.iterator();
        while(it.hasNext()){
            // 使用泛型之后,每一次迭代返回的数据都是Animal类型
            //Animal a = it.next();
            // 这里不需要进行强制类型转换了,直接调用
            //a.move();

            // 但是调用子类型特有的方法还是需要向下转换的
            Animal a = it.next();
            if(a instanceof Cat) {
                Cat x = (Cat)a;
                x.catchMouse();
            }
            if(a instanceof Bird) {
                Bird y = (Bird)a;
                y.fly();
            }
        }
	}
}

class Animal {
	// 父类自带方法
	public void move() {
		System.out.println("Animal move");
	}
}

class Cat extends Animal {
	// 特有方法
	public void catchMouse() {
		System.out.println("Cat move");
	}
}

class Bird extends Animal {
	// 特有方法
	public void fly() {
		System.out.println("Bird move");
	}
}

三、泛型的优缺点

  • 泛型的优点:
  1. 统一了集合中存储的元素类型
  2. 从集合中取出的元素类型是泛型指定的类型,不需要进行大量的“向下转型”
  • 泛型的缺点:
    集合中存储的元素缺乏多样性(但是大多数业务中,集合中元素的类型还是统一的,所以这种泛型缺点可以被大家所接受)

四、自动类型推断机制

  • JDK8之后引入了自动类型推断机制,又称为钻石表达式
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Test {
	public static void main(String[] args) {
		/**
		 * 自动类型推断机制
		 */
		// JDK8之后,<>里面的内容会进行自动类型推断
		List<Animal> myList = new ArrayList<>();

		myList.add(new Animal());
		myList.add(new Cat());
		myList.add(new Bird());

		// 遍历
		Iterator<Animal> it = myList.iterator();
		while (it.hasNext()) {
			Animal a = it.next();
			a.move();
		}

		List<String> strList = new ArrayList<>();

		// 类型不匹配
		// strList.add(new Cat());
		strList.add("abcdef");

		// 类型不匹配
		// strList.add(123)

		// 遍历
		Iterator<String> it2 = strList.iterator();
		while (it2.hasNext()) {
			// 如果没有使用泛型
			/*
			 * Object obj = it2.next(); if(obj instanceof String){ String s = (String)obj;
			 * s.substring(7); }
			 */
			// 直接通过迭代器获取了String类型的数据
			String s = it2.next();
			// 直接调用String类的substring方法截取字符串
			String newString = s.substring(3);
			System.out.println(newString);
		}
	}
}

五、自定义泛型

  • 自定义泛型的时候,<> 尖括号中的内容可以随便写(标识符),但一般写成<E>或者<T>,E是Element单词首字母,T是Type单词首字母
  • 自定义泛型后,不使用自定义泛型,则是Object类型
public class Test<E> {

	public void doSome(E o) {
		System.out.println(o);
	}

	public static void main(String[] args) {
		/**
		 * 自动类型推断机制
		 */
		// new对象的时候指定了泛型是:String类型
		Test<String> a = new Test<>();

		// 类型不匹配
		// gt.doSome(100);

		a.doSome("abc");

		// new对象的时候指定了泛型是:Integer类型
		Test<Integer> b = new Test<>();
		b.doSome(100);

		// 类型不匹配
		// gt2.doSome("abc");

		/*
		 * 不用泛型就是Object类型 
		 * Test gt3 = new Test(); 
		 * gt3.doSome(new Object());
		 */
	}
}

参考:深入理解 Java 泛型

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Jayco江柯

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

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

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

打赏作者

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

抵扣说明:

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

余额充值