2020-10-19泛型

泛型定义

泛型:是一种未知类型的数据当我们不知道使用什么类型的数据时,可以使用泛型;
例如: 单列集合Arraylist

public class ArrayList<E>{
	public boolean add(E e){};
	public E get(int index){}
}
E代表未知的数据
在创建对象的时候会把对象类型作为参数传递给泛型对象;
ArrayList对象的创建:
ArrayLIst<String> list = new ArrayList<>();
优点:把运行时异常提升到编译时异常,避免了转换的麻烦

以下不使用泛型:类型转换有误会产生运行时异常

 * @author HolyTrees
 * @date 2020-10-19  下午 13:56
 */
public class Demo01Generic {
    public static void main(String[] args) {
        show01();
    }

    /**
     * 创建集合对象,不使用泛型
     * 好处:
     *      集合不适用泛型;默认的类型就是Object类型,可以存储任意类型的数据
     * 弊端:
     *      不安全,会引发运行时异常
     */

    private static void show01() {
        //创建集合,默认是Object类型
        ArrayList list = new ArrayList();
        list.add("abc");
        list.add(123);
        /**
         * 使用迭代器遍历集合list
         */
        Iterator it= list.iterator();
        while (it.hasNext()){
           Object obj = it.next();
           System.out.println(obj);

            /**
             * 要使用String类特有的方法,length获取字符串长度,不能使用 多态 Object obj = "abc";
             * 需要向下转型;但是会抛出java.lang.ClassCastException 类型转换异常,
             * 不能把Integer类型转换成String类型
             */
            String s  = (String) obj;
            //获取字符串长度
            System.out.println(s.length());
        }
    }
}
输出结果为:
abc
字符串长度3
123
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

使用泛型:会产生编译时异常

import java.util.ArrayList;
import java.util.Iterator;

/**
 * @author HolyTrees
 * @date 2020-10-19  下午 14:24
 */
public class Demo02Generic {
    public static void main(String[] args) {
        show02();
    }

    /**
     * 创建对象 使用泛型
     *  好处:
     *      避免了类型转换的麻烦,存储的是什么类型,取出的就是什么类型
     *      把运行时异常提升到编译时异常;
     *  弊端:
     *      泛型是什么类型,只能存储什么类型的数据
     */
    private static void show02() {
        ArrayList<String> list = new ArrayList<>();
        list.add("abc");
        list.add("bbq");
        list.add(1);此处产生编译时异常
        //使用迭代器遍历list集合
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            String s = it.next();
            System.out.println(s+"字符串长度"+s.length());
        }
    }
}

泛型的使用

定义和使用含有泛型的类:
格式:public class 类名称
此处可以查看ArrayList源码来学习

定义和使用含有泛型的方法
格式:修饰符 返回值类型(参数列表(E e)){}

定义和实现含有泛型的接口
格式:public Interface 接口名称
实现方式:

  1. public class 类名称 Implements 接口名称 ,直接定义好实现类的泛型
  2. public class 类名称 Implements 接口名称 ,创建实现类对象是确定泛型类型

定义和使用含有泛型的方法

定义一个类,类中含有泛型对的普通的方法以及静态方法

/**
 * 定义一个含有泛型方法:泛型定义方法的修饰符和类型之间
 *  格式:
 *      修饰符 <泛型> 返回值类型 方法名(参数列表(使用泛型)) {
 *          方法体
 *      }
 *
 * @author HolyTrees
 * @date 2020-10-19  下午 14:56
 */
public class GenericMethod {
    /**
     * 传递什么参数,返回值就是什么类型,普通方法
     * @param e
     * @param <E> 定义泛型
     * @return
     */
  public <E> E show01(E e){
      System.out.println(e);
      return e;
  }

    /**
     * 静态方法
     *
     * @param e
     * @param <E>
     * @return
     */
  public static<E> E show02(E e){
      System.out.println(e);
      return e;
  }
}

测试主方法

/**
 * 测试含有泛型的方法
 *
 * @author HolyTrees
 * @date 2020-10-19  下午 14:58
 */
public class Demo01GenericMethod {
    public static void main(String[] args) {
        GenericMethod gc = new GenericMethod();
        /**
         * 传递参数给泛型
         */
        //String类型
        System.out.println("普通方法");
        System.out.println("传递String类型给泛型方法");
        gc.show01("普通泛型方法字符串");
        //Integer类型
        System.out.println("传递Integer类型给泛型方法");
        gc.show01(123);
        System.out.println();
        /**
         * 使用静态泛型方法
         */
        System.out.println("静态方法");
        System.out.println("传递String类型给泛型方法");
        GenericMethod.show02("静态泛型方法字符串");
        System.out.println("传递Integer类型给泛型方法");
        GenericMethod.show02(678);
    }
}
输出结果为:
普通方法
传递String类型给泛型方法
普通泛型方法字符串
传递Integer类型给泛型方法
123

静态方法
传递String类型给泛型方法
静态泛型方法字符串
传递Integer类型给泛型方法
678

定义和使用含有泛型的接口

定义泛型接口
/**
 * 定义泛型接口
 *
 * @author HolyTrees
 * @date 2020-10-19  下午 15:15
 */
public interface GenericInterface<E>{
    /**
     * 抽象方法使用接口泛型
     * @param e
     */
    void method(E e);
}
使用第一种实现方式

public class 类名称 Implements 接口名称 ,直接定义好实现类的泛型,此处使用String类型

/**
 * 含有泛型的接口使用方式:
 *  1.定义接口的实现类,实现接口,并且指定接口的泛型
 *      public interface Iterator<E>{
 *          E next();
 *      }
 *      Scanner类实现了Iterator接口,并指定接口的泛型为String,所以重写的next方法泛型默就是String
 *      public final class Scanner implements Iterator<String>{
 *          public String next(){};
 *      }
 *
 * @author HolyTrees
 * @date 2020-10-19  下午 15:17
 */
public class GenericImplOne implements GenericInterface<String>{

    @Override
    public void method(String s) {
        System.out.println(s);
    }
}
使用第二种实现方式

public class 类名称 Implements 接口名称 ,创建实现类对象是确定泛型类型

/**
 * 含有泛型的接口第二种使用方式:接口使用泛型,实现类就是用什么泛型
 * 相当于定义了一个含有泛型的类,创建对象的时候确定泛型的类型
 *  public interface list<E>{
 *      public boolean add(E e);
 *      E get(int index);
 *  }
 *  public class Arraylist<E> implements list<E>{
 *       public boolean add(E e);
 *  *    E get(int index);
 *  }
 *
 * @author HolyTrees
 * @date 2020-10-19  下午 15:33
 */
public class GenericImplTwo<E> implements GenericInterface<E>{
    @Override
    public void method(E e) {
        System.out.println(e);
    }
}
主方法测试
/**
 * 定义主方法,测试含有泛型的接口
 *
 * @author HolyTrees
 * @date 2020-10-19  下午 15:29
 */
public class Demo01GenericInterface {
    public static void main(String[] args) {

        //创建GenericImplOne的对象
        GenericImplOne gc = new GenericImplOne();
        gc.method("No matter how far we go");
        //创建GenericImplTwo的对象
        GenericImplTwo<Integer> gc2 = new GenericImplTwo<>();
        gc2.method(132);

        GenericImplTwo<String> gc3 = new GenericImplTwo<>();
        gc3.method("String类型");

    }
}
输出结果为:
No matter how far we go
132
String类型

泛型通配符

泛型通配符的高级使用—受限泛型
之前设置泛型的时候,实际上可以是任意设置的,只要是类就可以设置,但是在JAVA的泛型中可以指定一个泛型的上限和下限。
泛型的上限:
格式: 类型名称 <? Extend E> 对象名称
意义:只能接收该类型及其子类
犯下的下限:
格式:类型名称<? Super E>对象名称
意义:只能接收该类型及其父类型

import java.util.ArrayList;
import java.util.Collection;

/**
 * 泛型通配符的高级使用:
 *  泛型通配符的上限:
 *      格式 :类型名称<? extend 类>对象名称
 *      意义:只能接收该类型及其子类型
 *  泛型通配符的下限:
 *      格式:类型名称<? super 类>对象名称
 *      意义:只能接收该类型及其父类型
 *
 * @author HolyTrees
 * @date 2020-10-19  下午 16:20
 */
public class GenericModifierLimit {
    public static void main(String[] args) {
        /**
         * Number是Integer父类
         * Object是Number的父类
         */
        Collection<Integer> list1 = new ArrayList<Integer>();
        Collection<String> list2 = new ArrayList<String>();
        Collection<Number> list3 = new ArrayList<Number>();
        Collection<Object> list4 = new ArrayList<Object>();

        getElements1(list1);
        getElements1(list2); 报错String类型不属于Number泛型的上限
        getElements1(list3);
        getElements1(list4); 报错Object是Number的父类,属于下限

        getElements2(list1); 报错 Integer是Number的子类,属于上限
        getElements2(list2); 报错 String类型不属于Number泛型的下限
        getElements2(list3);
        getElements2(list4);

    }
    /**
     * 泛型的上限:此时的泛型必须是Number及其子类
     * @param coll
     */
    public static void getElements1(Collection<? extends Number> coll){};

    /**
     * 泛型的下限:此时的泛型必须是Number及其父类
     * @param coll
     */
    public static void getElements2(Collection<? super Number> coll){}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值