corejava 第十六天

泛型

泛型是JDK1.5及以上才可以使用的特性/语法,它的本质是 类型参数化(Parameterized by types).

类型参数化,可以在编译器阻止用户非法输入,在运行时减少ClassCastException的抛出

通常使用的泛型参数变量名:

T:Type

E:Element

K:Key

V:Value

泛型的种类

  • 泛型类
  • 泛型接口
  • 泛型方法

泛型类,如果泛型参数定义在类上面,那么这个类就是一个泛型类

在类中,就可以使用这个T来代表某一个类型,这个类型具体是什么将来使用的时候再传参确定

		public class Point<T>{...}
        public static void main(String[] args){
            Point<String> p = new Point<>();
        }

泛型接口,如果泛型参数定义在接口上面,那么这个接口就是一个泛型接口

在接口中,就可以使用这个T来代表某一个类型,这个类型具体是什么将来使用的时候再传参确定

		public interface Action<T>{...}
        public static void main(String[] args){
//创建匿名内部类
            Action<String> a = new Action<>(){
//...
            };
        }

泛型方法,如果泛型参数定义在方法上面,那么这个方法就是一个泛型方法

        public class Test{
            public <T> T test(T t){
//..
            }
        }
        public static void main(String[] args){
            Test t = new Test();
            String str = t.test("hello");
            Integer i = t.test(1);
            Double d = t.test(10.5D);
        }

可以看出,调用test方法时候,我们传什么类型的参数,test方法的返回类型就是什么类型的。 这种效果,在不使用泛型的情况下,是不可能实现的。

泛型的类型

Object o = new Integer(1); //编译通过
ArrayList<Object> list = new ArrayList<Integer>(); //编译报错

虽然 Integer 是 Object 的子类型,但是 ArrayList 和 ArrayList 之间没有子 父类型的关系,它们就是俩个不同的类型

也就是说,俩个类型,如果是当做泛型的指定类型的时候,就没有多态的特点了

通配符

public void test1(Collection<Integer> c){
}
public void test2(Collection<String> c){
}
public void test3(Collection<Object> c){
}

test1方法【只能】接收泛型是Integer类型的集合对象

test2方法【只能】接收泛型是String类型的集合对象

test3方法【只能】接收泛型是Object类型的集合对象

原因:由于泛型的类型之间没有多态,所以=号俩边的泛型类型必须一致

在这种情况下,就可以使用通配符(?)来表示泛型的父类型:

public void test(Collection<?> c){
}
注意,这时候test方法中的参数类型,使用了泛型,并且使用问号来表示这个泛型的类型,这个问
号就是通配符,可以匹配所有的泛型类型
test方法可以接收 泛型是任意类型的 Collection集合对象

泛型范围

在泛型中使用extends和super可以对泛型的上下限进行限制

泛型的上限:

  • 例如: List<? extends Number> list
  • 将来引用list就可以接收泛型是 Number 或者 Number 子类型的List集合对象
 	public static void main(String[] args) {
            List<? extends Number> list;
		//list可以指向泛型是Number或者Number【子】类型的集合对象
            list = new ArrayList<Number>();
            list = new ArrayList<Integer>();
            list = new ArrayList<Double>();
		//编译报错,因为String不是Number类型,也不是Number的子类型
			//list = new ArrayList<String>();
        }

能表示数字的类型都是Number类型的子类型,例如Byte Short Integer Long等

泛型的下限:

  • 例如: List<? super Number> list
    
  • 将来引用list就可以接收泛型是 Number 或者 Number 父类型的List集合对象

public static void main(String[] args) {
List<? super Number> list;
//list可以指向泛型是Number或者Number【父】类型的集合对象
list = new ArrayList<Number>();
list = new ArrayList<Serializable>();
list = new ArrayList<Object>();
//编译报错,因为String不是Number类型,也不是Number的父类型
//list = new ArrayList<String>();
//编译报错,因为Integer不是Number类型,也不是Number的父类型
//list = new ArrayList<Integer>();
}

泛型中 extends 和 super 对比:

  • 使用extends可以定义泛型的【上限】,这个就表示将来泛型所接收的类型【最大】是什么类型。 可以是这个最大类型或者它的【子类型】。
  • 使用super可以定义泛型的【下限】,这个就表示将来泛型所接收的类型【最小】是什么类型。可 以是这个【最小类型】或者它的【父类型】。

extends 限定泛型的上限的使用场景

  1. 在声明泛型类或者泛型接口的时候【可以】使用
  2. 在声明泛型方法的时候【可以】使用
  3. 在声明变量的时候【可以】使用

super 限定泛型的下限的使用场景

  1. 在声明泛型类或者泛型接口的时候【不能】使用
  2. 在声明泛型方法的时候【不能】使用
  3. 在声明变量的时候【可以】使用

类型擦除

泛型类型仅存在于编译期间,编译后的字节码和运行时不包含泛型信息,所有的泛型类型映射到同一份 字节码。

由于泛型是JDK1.5才加入到Java语言特性的,Java让编译器擦除掉关于泛型类型的信息,这样使得Java 可以向后兼容之前没有使用泛型的类库和代码,因为在字节码(class)层面是没有泛型概念的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值