泛型(参数化类型)

------------恢复内容开始------------

一、泛型的概念

泛型:即参数化类型,把类型明确的工作推迟到创建对象或调用方法的时候才去明确的特殊的类型,简而言之,就是在定义一个对象的时候没有赋予确切的参数类型,在实例化一个对象的时候传递确切的参数,类似于形参和实参的一种情况。

Java泛型设计原则:只要在编译时期没有出现警告,那么运行时期就不会出现ClassCastException异常.

Java泛型的设计目的:主要是为了解决当向一个集合输入不同的数据类型时,输出读取时会报错的问题,例如向一个集合中添加字符串、数字、字符等类型的数据时,当输出时会报错误。

相关术语:

  • ArrayList<E>中的E称为类型参数变量,常用的类型参数符号有K、E、V、M
  • ArrayList<Integer>中的Integer称为实际类型参数
  • 整个称为ArrayList<E>泛型类型
  • 整个ArrayList<Integer>称为参数化的类型ParameterizedType

二、为什么需要泛型

早期Java是使用Object来代表任意类型的,但是向下转型有强转的问题,这样程序就不太安全

首先,我们来试想一下:没有泛型,集合会怎么样

  • 把对象扔进集合中,集合是不知道元素的类型是什么的,仅仅知道是Object。因此在get()的时候,返回的是Object。外边获取该对象,还需要强制转换
  • Collection、Map集合对元素的类型是没有任何限制的。本来我的Collection集合装载的是全部的Dog对象,但是外边把Cat对象存储到集合中,是没有任何语法错误的。

2.1有了泛型后使用增强foreach遍历集合

//创建集合对象
        ArrayList<String> list = new ArrayList<>();

        list.add("hello");
        list.add("world");
        list.add("java");

        //遍历,由于明确了类型.我们可以增强for
        for (String s : list) {
            System.out.println(s);
        }

三、泛型分类

泛型的分类主要分为:泛型类、泛型接口、泛型方法

3.1 泛型类

泛型类就是把泛型定义在类上,用户使用该类的时候,才把类型明确下来....这样的话,用户明确了什么类型,该类就代表着什么类型...用户在使用的时候就不用担心强转的问题,运行时转换异常的问题了。

3.1.1类的定义:

/*
    1:把泛型定义在类上
    2:类型变量定义在类上,方法中也可以使用
 */
public class ObjectTool<T> {
    private T obj;//变量的数据类型和泛型类所传递的数据类型一致

    public T getObj() {//函数的返回类型和泛型类所传递的数据类型一致
        return obj;
    }

    public void setObj(T obj) {
        this.obj = obj;
    }
}

测试代码:

 public static void main(String[] args) {
        //创建对象并指定元素类型为字符串类型
        ObjectTool<String> tool = new ObjectTool<>();
        tool.setObj("一只懒熊");
        String s = tool.getObj();
        System.out.println(s);

        //创建对象并指定元素类型为整数类型
        ObjectTool<Integer> objectTool = new ObjectTool<>();
        /*
          如果我在这个对象里传入的是String类型的,它在编译时期就通过不了了.
         */
        objectTool.setObj(10);
        int i = objectTool.getObj();
        System.out.println(i);
    }

3.1.2泛型类的继承:泛型类是拥有泛型这个特性的类,它本质上还是一个Java类,那么它就可以被继承

那它是怎么被继承的呢?这里分两种情况

  1. 子类明确泛型类的类型参数变量
  2. 子类不明确泛型类的类型参数变量

情况1:子类明确泛型类的类型参数变量

//把泛型定义在接口上
public interface Inter<T> {
    public abstract void show(T t);
}

//定义一个子类来实现接口
public class InterImpl implements Inter<String> {//子类明确泛型类的类型参数变量为String:
    @Override
    public void show(String s) {
        System.out.println(s);

    }
}

//测试代码
public class mingquefanxingcanshu {
    public static void main(String[] args) {
        Inter<String> i = new InterImpl();
        i.show("hello java!");
    }
}

情况2:子类不明确泛型类的类型参数变量

//把泛型定义在接口上
public interface Inter<T> {
    public abstract void show(T t);
}

//定义一个子类来实现接口
public class InterImpl<T> implements Inter<T> {//实现类不明确泛型类的类型参数变量,实现类也要定义出<T>类型的
    @Override
    public void show(T s) {//子类方法也要继承类的数据类型T
        System.out.println(s);

    }
}

//测试代码
public class mingquefanxingcanshu {
    public static void main(String[] args) {
        Inter<String> i = new InterImpl();
        i.show("hello java!");
    }
}

注意:

  • 实现类的要是重写父类的方法,返回值的类型是要和父类一样的!
  • 类上声明的泛形只对非静态成员有效

------------恢复内容结束------------

猜你喜欢

转载自www.cnblogs.com/ibear/p/12490971.html