JAVA网络爬虫
HttpClient

导航

 

泛型

  1. 使用泛型的好处

    • 执行路口

      package cn.xiaoge.day13.demo03;
      
      import java.util.ArrayList;
      import java.util.Iterator;
      
      public class Demo01Generic {
      
          public static void main(String[] args) {
              show01();
              System.out.println("====================");
              show02();
          }
      
      
          /*
              创建集合对象, 使用泛型
              好处:
                  1. 避免了类型转换的麻烦, 存储的是什么类型, 取出的就是什么类型
                  2. 把运行期异常(代码运行之后会抛出的异常), 提升到了编译期(写代码的时候会报错).
              弊端:
                  泛型是什么类型, 只能存储什么类型的数据
           */
          private static void show02() {
              ArrayList<String> list = new ArrayList<>();
              list.add("abc");
              // list.add(1); // add(java.lang.String) in ArrayList cannot be applied to (int)
      
              // 使用迭代器遍历list集合
              Iterator<String> it = list.iterator();
              while(it.hasNext()) {
                  String s = it.next();
                  System.out.println(s + "--->" + s.length());
              }
          }
      
      
          /*
              创建集合对象, 不适用泛型
              好处:
                  集合不适用泛型, 默认的类型就是Object类型, 可以存储任意类型的数据
              弊端:
                  不安全, 会引发异常
           */
          private static void show01() {
      
              ArrayList list = new ArrayList();
              list.add("abc");
              list.add(1);
      
              // 适用迭代器遍历list集合
              // 获取迭代器
              Iterator it = list.iterator();
              // 使用迭代器中的方法hasNext和next遍历集合
              while(it.hasNext()) {
                  // 取出元素也是Object类型
                  Object obj = it.next();
                  System.out.println(obj);
      
      
                  // 想要使用String类特有的方法, length获取字符串的长度; 不能使用 多态 Object obj = "abc";
                  // 需要向下转型
                  // 会抛出ClassCastException类型转换异常, 不能把Integer类型转换为String类型
                  // String s = (String) obj;
                  // System.out.println(s.length());
              }
      
          }
      
      }
      
      // 运行结果
      abc
      1
      ====================
      abc--->3
      
  2. 定义和使用含有泛型的类

    • 泛型类

      package cn.xiaoge.day13.demo03;
      
      /*
          定义一个含有泛型的类, 模拟ArrayList集合
      
          泛型是一个未知的数据类型, 当我们不确定使用什么数据类型的时候, 可以使用泛型.
      
          泛型可以接收任意的数据类型, 可以使用Integer, String, Student.....
      
          创建对象的时候确定泛型的数据类型
       */
      
      public class GenericClass<E> {
      
          private E name;
      
          public E getName() {
              return name;
          }
      
          public void setName(E name) {
              this.name = name;
          }
      }
      
    • 执行路口

      package cn.xiaoge.day13.demo03;
      
      public class Demo02GenericClass {
      
          public static void main(String[] args) {
      
              // 不写泛型默认为Object类型
              GenericClass gc1 = new GenericClass();
              gc1.setName("只能是字符串");
              Object obj = gc1.getName();
              System.out.println(obj); // 只能是字符串
              System.out.println("===========================");
      
              // 创建GenericClass对象, 泛型使用Integer类型
              GenericClass<Integer> gc2 = new GenericClass<>();
              gc2.setName(10);
              int num = gc2.getName();
              System.out.println(num); // 10
              System.out.println("===========================");
      
              // 创建GenericClass对象, 泛型使用String类型
              GenericClass<String> gc3 = new GenericClass<>();
              gc3.setName("张三");
              String name = gc3.getName();
              System.out.println(name); // 张三
          }
      
      }
      
      // 运行结果
      只能是字符串
      ===========================
      10
      ===========================
      张三
      
  3. 定义和使用含有泛型的方法

    • 含有泛型方法的类

      package cn.xiaoge.day13.demo03;
      
      /*
          定义含有泛型的方法: 泛型定义在方法的修饰符和返回值之间
      
          格式:
              修饰符 <泛型> 返回值类型 方法名(参数列表(使用泛型)) {
                  方法体;
              }
          含有泛型的方法, 在调用方法的时候确定泛型的数据类型
          传递什么类型的参数, 泛型就是什么类型
       */
      
      public class GenericMethod {
      
          // 定义一个含有泛型的方法, 记住: 泛型里面的符号使用什么都可以
          public <M> void method01(M m) {
              System.out.println(m);
          }
      
          // 定义一个含有泛型的静态方法
          public static <E> void method02(E e) {
              System.out.println(e);
          }
      
      }
      
    • 执行路口

      package cn.xiaoge.day13.demo03;
      
      /*
          测试含有泛型的方法
       */
      
      public class Demo03GenericMethod {
      
          public static void main(String[] args) {
              // 创建GenericMethod对象
              GenericMethod gm = new GenericMethod();
      
              /*
                  调用含有泛型的方法method01
                  传递什么类型, 泛型就是什么类型
               */
              gm.method01(10);
              gm.method01("abc");
              gm.method01(10.2);
              gm.method01(true);
              System.out.println("=====================");
      
              gm.method02("静态方法不建议创建对象使用");
              // 静态方法, 通过类名.方法名(参数)可以直接使用
              GenericMethod.method02("技能太方法建议用类名称使用");
              GenericMethod.method02(1);
          }
      
      }
      
      // 运行结果
      10
      abc
      10.2
      true
      =====================
      静态方法不建议创建对象使用
      技能太方法建议用类名称使用
      1
      
  4. 定义和使用含有泛型的接口–这里有两种方法–分别是两个类

    • 接口

      package cn.xiaoge.day13.demo03;
      
      /*
          定义含有泛型的接口
       */
      
      public interface GenericInterface<E> {
      
          public abstract void method(E e);
      
      }
      
    • GenericInterfaceImpl1类

      package cn.xiaoge.day13.demo03;
      
      /*
          含有泛型接口, 第一种使用方式: 定义接口的实现类, 实现接口, 指定接口泛型
          public interface Iterator<E> {
              E next();
          }
      
          Scanner类实现了Iterator接口, 并指定接口的泛型为String, 所以重写的next方法泛型默认就是String
          public final class Scanner implements Iterator<String> {
              public String next() {}
          }
       */
      
      public class GenericInterfaceImpl1 implements GenericInterface<String> {
      
          @Override
          public void method(String s) {
              System.out.println(s);
          }
      
      }
      
      
    • GenericInterfaceImpl2类

      package cn.xiaoge.day13.demo03;
      
      /*
          含有泛型的接口第二种使用方式: 接口使用什么泛型, 实现类就是用什么泛型, 类跟着接口走
          就相当于定义了一个含有泛型的类, 创建对象的时候确定泛型的类型
      
          public interface List<E> {
              boolean add(E e);
              E get(int index);
          }
      
          public class ArrayList<E> implements list<E>{
              public boolean add(E e) {}
              public E get(int index) {}
          }
       */
      
      public class GenericInterfaceImpl2<E> implements GenericInterface<E> {
          @Override
          public void method(E e) {
              System.out.println(e);
          }
      }
      
    • 执行路口

      package cn.xiaoge.day13.demo03;
      
      /*
          测试含有泛型的接口
       */
      
      public class Demo04GenerciInterface {
      
          public static void main(String[] args) {
              // 创建GenericInterfaceImpl1对象
              GenericInterfaceImpl1 impl1 = new GenericInterfaceImpl1();
              impl1.method("哈哈");
              System.out.println("==================");
      
              // 创建GenericInterfaceImpl2对象
              GenericInterfaceImpl2<Integer> impl2 = new GenericInterfaceImpl2<>();
              impl2.method(10);
      
              GenericInterfaceImpl2<Double> impl3 = new GenericInterfaceImpl2<>();
              impl3.method(20.34);
          }
      
      }
      
      // 运行结果
      哈哈
      ==================
      10
      20.34
      
  5. 泛型通配符?

    • 执行路口–普通用法

      package cn.xiaoge.day13.demo03;
      
      /*
          泛型的通配符:
              ?: 代表任意的数据类型
          使用方式:
              不能创建对象使用
              只能作为方法的参数使用
       */
      
      import java.util.ArrayList;
      import java.util.Iterator;
      
      public class Demo05Generic {
      
          public static void main(String[] args) {
              ArrayList<Integer> list01 = new ArrayList<>();
              list01.add(1);
              list01.add(2);
              ArrayList<String> list02 = new ArrayList<>();
              list02.add("a");
              list02.add("b");
              printArray1(list01);
              printArray1(list02);
              System.out.println("");
              System.out.println("============================");
              printArray2(list01);
              printArray2(list02);
          }
      
      
          /*
              定义一个方法能遍历所有类型的ArrayList集合
              这时候我们不知道ArrayList集合使用什么数据类型,
              可以使用泛型的通配符?来接受数据类型
      
              注意:
                  泛型没有继承概念的
           */
          private static void printArray1(ArrayList<?> list) {
              // 使用迭代器遍历集合
              Iterator<?> it = list.iterator();
              while(it.hasNext()){
                  System.out.print(it.next());
              }
          }
      
      
          private static <E> void printArray2(ArrayList<E> list) {
              // 使用迭代器遍历集合
              Iterator<E> it = list.iterator();
              while(it.hasNext()){
                  System.out.print(it.next());
              }
          }
      }
      
      // 运行结果
      12ab
      ============================
      12ab
      
    • 执行路口–高级用法

      package cn.xiaoge.day13.demo03;
      
      /*
          泛型的上线限定: ? extends E 代表使用的泛型只能是E类型的子类/本身
          泛型的下线限定: ? super E   代表使用的泛型只能是E类型的父类/本身
       */
      
      import java.util.ArrayList;
      import java.util.Collection;
      
      
      public class Demo06Generic {
      
          public static void main(String[] args) {
              Collection<Integer> list1 = new ArrayList<>();
              Collection<String> list2 = new ArrayList<>();
              Collection<Number> list3 = new ArrayList<>();
              Collection<Object> list4 = new ArrayList<>();
      
              getElement1(list1);
              // getElement1(list2); // 报错
              getElement1(list3);
              // getElement1(list4); // 报错
      
              // getElement2(list1); // 报错
              // getElement2(list2); // 报错
              getElement2(list3);
              getElement2(list4);
      
              /*
                  类与类之间的继承关系
                  Integer extends Number extends Object
                  String extends Object
               */
      
          }
      
          // 泛型的上限: 此时的泛型?, 必须是Number类型或者Number类型的子类
          public static void getElement1(Collection<? extends Number> coll) {}
          // 泛型的下限: 此时的泛型?, 必须是Number类型或者Number类型的父类
          public static void getElement2(Collection<? super Number> coll) {}
      
      }
      
posted on 2019-10-28 13:20  gmlgxx  阅读(34)  评论(0)    收藏  举报