JAVA14——泛型

目录

引入

概述

泛型类

泛型接口:定义类时使用泛型

泛型方法

泛型子类

泛型擦除

泛型没有多态

通配符

泛型嵌套

泛型与数组

JDK7泛型改进


引入

一个学生的成绩有三种情况,应如何处理?

1、整数

2、小数

3、字符串

代码:

student.java

public class Student {
	private Object javase;
	private Object oracle;
	
	
	public Student(Object javase, Object oracle) {
		super();
		this.javase = javase;
		this.oracle = oracle;
	}
	public Object getJavase() {
		return javase;
	}
	public void setJavase(Object javase) {
		this.javase = javase;
	}
	public Object getOracle() {
		return oracle;
	}
	public void setOracle(Object oracle) {
		this.oracle = oracle;
	}
}

app.java

/**
 * 获取值:
 * 1.强制类型转换
 * 2.手动类型检查:避免转换错误:java.lang.ClassCastException
 * @author qiao39gs
 *
 */
public class App {

	public static void main(String[] args) {
		Object obj = 80;
		//int score = (int)obj;	//jdk1.7以后:Object—Integer—自动拆箱
		int score = (Integer) obj;	//jdk1.6及以前版本
		System.out.println(score);
		
		//存入整数:int—Integer—Object
		Student stu = new Student(80,90);
		
		int javaseScore = (Integer) stu.getJavase();
		String oracleScore = null;
		if(stu.getOracle() instanceof String){
			oracleScore = (String) stu.getOracle();
		}
		System.out.println("分数为:"+javaseScore+","+oracleScore);
	}
	
}

不能将oracle的成绩转换为String类型

概述

  • 概念:泛型就是参数化类型,使用广泛的类型。
  • 起因:数据类型不明确:
    • 装入数据的类型都被当作Object对待,从而“丢失”自己的实际类型。 
    • 获取数据时往往需要转型,效率低,容易产生错误
  • 作用:
    • 安全:在编译的时候检查类型安全
    • 省心:所有的强制转换都是自动和隐式的,提高代码的重用率

泛型类

  • 格式:<>
    class类名<字母列表>{
    修饰符 字母 属性 ;
    修饰符 构造器(字母){

    }
    修饰符 返回类型 方法(字母){

    }
    不能使用在静态属性、静态方法上
  • 使用:指定具体类型
    1.编译时会进行类型检查;
    2.获取数据时不需要强制类型转换。
    泛型使用时不能指定基本类型。
  • 泛型常见字母
    T Type表示类型
    K V 分别代表键值中的Key Value
    E 代表 Element
    ?表示不确定的类型

eg:

/**
 * 泛型类:声明时使用泛型
 * 使用时确定类型
 * @author qiao39gs
 *
 * @param <T>
 */
public class Student<T1,T2> {
	private T1 javaScore;
	private T2 oracleScore;
	
	//private static T1 test;	//不能使用静态属性|静态方法上
	
	public T1 getJavaScore() {
		return javaScore;
	}

	public void setJavaScore(T1 javaScore) {
		this.javaScore = javaScore;
	}

	public T2 getOracleScore() {
		return oracleScore;
	}

	public void setOracleScore(T2 oracleScore) {
		this.oracleScore = oracleScore;
	}

	public static void main(String[] args) {
		//使用时指定类型
		Student<String,Integer> stu = new Student<String,Integer>();
		//1.安全:类型检查
		stu.setJavaScore("优秀");
		//2.省心:类型转换
                stu.setOracleScore(93);
		int it = stu.getOracleScore();	//自动拆箱
	}
	
}

泛型接口:定义类时使用泛型

  1. 格式:<>
    interface 接口名 <字母列表>{
            修饰符 返回类型 方法(字母);
    }
  2. 因为不能使用在静态属性上,更不能用在全局常量上

eg:

/**
 * 接口中泛型字母只能使用在方法中,不能使用在全局常量中
 * @author qiao39gs
 *
 * @param <T>
 */
public interface Comparator<T> {
	void compare(T t);
}

泛型方法

  • 定义使用:<字母>
    修饰符 <字母> 返回类型 方法名(字母){

    }
    要定义泛型方法,只需将于泛型参数列表置返回值前
  • 注意:泛型还可以定义在方法中,是否拥有泛型方法,与其所在的类是否泛型没有关系

eg:

/**
 * 泛型方法<> 返回类型签名
 * 只能访问对象的信息,不能修改信息
 * @author qiao39gs
 *
 */
public class TestMethod {
	
	public static void main(String[] args) {
		test("a");	//T—String
	}
	//泛型方法
	public static<T> void test(T a){
		System.out.println(a);
	}
}

泛型子类

  • 子类与父类|接口一样使用泛型
  • 子类指定具体的类型
  • 子类与父类|接口同时擦除类型
  • 子类泛型,父类接口 擦除
  • 错误:不能子类擦除,父类|接口泛型

擦除统一使用 Object对待

eg:

/**
 * 父类为泛型类
 * 1.属性
 * 2.方法
 * 
 * 要么同时擦除,要么子类大于等于父类的类型
 * 不能子类擦除,父类泛型
 * 1.属性类型
 * 父类中,随子类而定
 * 子类中,随子类而定
 * 2.方法重写:
 * 随父类而定
 * 
 * 
 * @author qiao39gs
 *
 * @param <T>
 */
public abstract class Father<T,T1> {
	T name;
	public abstract void test(T t);
}
/**
 * 子类声明时指定具体类型
 * 属性类型为具体类型
 * 方法同理
 */
class Child1 extends Father<String,Integer>{
	String t2;
	@Override
	public void test(String t){
		
	}
}
/**
 * 子类为泛型类,类型在使用时确定
 * @param <T1>
 * @param <T>
 */
class Child2<T1,T> extends Father<T,T1>{
	T t2;
	@Override
	public void test(T t){
		
	}
}
/**
 * 子类为泛型,父类不指定类型,泛型的擦除,使用Object替换
 * @param <T1>
 * @param <T>
 */
class Child3<T1,T2> extends Father{
	
	@Override
	public void test(Object t){
		
	}
}
/**
 * 子类与父类同时擦除
 */
class Child4 extends Father{
	String name;
	@Override
	public void test(Object t) {
		// TODO Auto-generated method stub
		
	}
	
}
/**
 * 错误:子类擦除,父类使用泛型
class Child5 extends Father<T,T1>{
	String name;
	@Override
	public void test(T t) {
		// TODO Auto-generated method stub
		
	}
}
*/

泛型擦除

  • 擦除:
    • 在使用时没有指定具体的类型
    • 子类继承时没有指定类型
  • 处理:
    • 擦除后不类型检查
    • 一旦擦除之后按Object接收
    • 依然存在编译警告,加上 Object可以去除,但是有些画蛇添足

eg:

/**
 * 泛型接口:与继承同理
 * 重写方法随父类而定
 * @author qiao39gs
 *
 * @param <T>
 */
public interface Comparable<T> {
	void compare(T t);
}
//声明子类指定具体类型
class Comp implements Comparable<Integer>{

	@Override
	public void compare(Integer t) {
		// TODO Auto-generated method stub
		
	}
	
}
//擦除
class Comp1 implements Comparable{

	@Override
	public void compare(Object t) {
		// TODO Auto-generated method stub
		
	}
	
}
//父类擦除,子类泛型
class Comp2<T> implements Comparable{

	@Override
	public void compare(Object t) {
		// TODO Auto-generated method stub
		
	}
	
}
//子类泛型>=父类泛型
class Comp3<T> implements Comparable<T>{

	@Override
	public void compare(T t) {
		// TODO Auto-generated method stub
		
	}
	
}
//父类泛型,子类擦除	错误

eg2:

/**
 * 泛型的擦除
 * 1.继承|声明不指定类型
 * 2.使用时不指定类型
 * 统一Object对待
 * 	1.编译器警告(Student is a raw type. References to generic type Student<T> should be parameterized)
 *    消除警告:加<Object>
 *  2.不完全等同于Object,编译不会类型检查
 * @author qiao39gs
 *
 * @param <T>
 */
public class Student<T> {
	private T javaScore;
	private T oracleScore;
	
	//private static T1 test;	//不能使用静态属性|静态方法上
	
	public T getJavaScore() {
		return javaScore;
	}

	public void setJavaScore(T javaScore) {
		this.javaScore = javaScore;
	}

	public T getOracleScore() {
		return oracleScore;
	}

	public void setOracleScore(T oracleScore) {
		this.oracleScore = oracleScore;
	}

	public static void main(String[] args) {
		Student stu = new Student();
		//消除警告使用Object
		Student<Object> stu1 = new Student<Object>();
		stu1.setJavaScore("A");  //以Object对待
		
		test(stu);	//stu相当于 Object但是不完全等同 Object
		//擦除,不会类型检查
		//test(stu1);	
		test1(stu);
		test1(stu1);
	}
	
	public static void test(Student<Integer> a){
		
	}
	
	public static void test1(Student<?> a){
		
	}
	
}

泛型没有多态

  1. 回顾类与接口存在多态
  2. 泛型没有多态
    直接使用:A< Object> a = new A< String>();  错误
    方法形参与返回类型也不存在泛型多态
  3. 不能使用instanceof判断是否为泛型实例
    a instanceof A<String>

多态的两种形式eg:

Fruit.java:

public class Fruit {

}
class Apple extends Fruit{
	
}

 FruitApp.java

public class FruitApp {

	public static void main(String[] args) {
		Fruit f = new Apple();
		test(new Apple());
	}
	
	//形参使用多态
	public static void test(Fruit f){
		
	}
	
	//返回类型使用多态
	public static Fruit test2(){
		return new Apple();
	}
	
}

 泛型不能使用多态:

 A.java

public class A<T> {

}

 App.java

public class App {
	
	public static void main(String[] args) {
		//A<Fruit> f = new A<Apple>();	报错:Type mismatch: cannot convert from A<Apple> to A<Fruit>
		A<Fruit> f = new A<Fruit>();
		//test(new A<Apple>());	报错:The method test(A<Fruit>) in the type App is not applicable for the arguments (A<Apple>)
	}
	
	//形参使用多态
	public static void test(A<Fruit> f){
		
	}
	//返回类型使用多态
	public static A<Fruit> test2(){
		//return (A<Fruit>) (new A<Apple>());	报错:Cannot cast from A<Apple> to A<Fruit>
		return null;
	}
	
}

通配符

? extends super

  1. 可以用在声明类型及声明方法参数上,不能用在声明类上
  2. ?可以接受泛型的任意类型,只能接收和输出,不能修改
           方法声明时参数无法正确知道具体的类型,因此不能修改
  3. ? extends    泛型上限    <=
  4. ? super        泛型下限    >=
/**
 * ?类型不定,使用时确定类型
 * ?的使用:声明类型|声明方法上,不能声明类或使用时
 * ? extends <=   泛型上限  指定类型 子类或自身
 * ? super   >=   泛型下限  指定类型为自身或父类  
 * @author qiao39gs
 *
 */
public class Student<T> {
	T score;
	
	public static void main(String[] args) {
		Student<?> stu = new Student<String>();
		test(new Student<Integer>());
		
		test2(new Student<Apple>());
		//test3(new Student<Apple>());	//泛型没有多态
		
		//test4(new Student<Apple>());	//<
		stu = new Student<Fruit>();
		//test4(stu);	//使用时确定类型 
		test4(new Student<Object>());
		test4(new Student<Fruit>());
	}
	
	public static void test(Student<?> stu){
		
	}
	
	public static void test3(Student<Fruit> stu){
		
	}
	// <=
	public static void test2(Student<? extends Fruit> stu){
		
	}
	// >=
	public static void test4(Student<? super Fruit> stu){
		
	}
}

泛型嵌套

  1. 声明:嵌套使用泛型
    A<B<C>> a = new A<B<C>>();
  2. 使用:从外到内,一层层拆分
    稍微复杂一些,与调用没有任何的关系,只确定了类型
public class Nest <T> {
	T stu;
	
	public static void main(String[] args) {
		//泛型的嵌套
		Nest<Student<String>> room = new Nest<Student<String>>();
		//从外到内拆分
		room.stu = new Student<String>();
		Student<String> stu = room.stu;
		String score = stu.score;
		System.out.println(score);
	}
	
}

泛型与数组

  • 没有泛型数组,不能创建泛型数组
  • 可以只有声明,可以使用?
  • A<String>[] a1 = null;
  • A<?>[] a2 = new A<?>[10];
public class Array {
	
	public static void main(String[] args) {
		Student<?>[] arr2 = new Student[10];
		
		MyArrayList<String> strList = new MyArrayList<String>();
		strList.add(0,"aa");
		String elem = strList.getElem(0);
		System.out.println(elem);
	}
	
}
class MyArrayList<E>{
	//E[] cap = new E[10];	没有泛型数组
	Object[] cap = new Object[10];
	
	public void add(int idx,E e){
		cap[idx] = e;
	}
	
	public E[] getAll(){
		return (E[]) cap;
	}
	
	public E getElem(int idx){
		return (E) cap[idx];
	}
}

JDK7泛型改进

  • jdk7改进:声明时指定泛型即可,创建对象不用再次编写类型
  • 如  A<String> a = new A<>0;
public class Test7 {
	
	public static void main(String[] args) {
		List<String> arrList = new ArrayList<String>();
		List<String> arrList2 = new ArrayList<>();
	}
	
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值