Java学习笔记123——集合—泛型

泛型

泛型的定义及优点

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

/*
        ClassCastException:类型转换异常
        我们按照正常的写法,在集合中添加一些不是同类型的数据,在遍历的时候向下转型
        报错了。

        为什么呢?
            因为我们在存储数据的时候,存储了一些String和Integer类型的数据
            但是呢,我们遍历的时候,默认集合中只存放String类型的数据,但是呢,又没有在
            存储数据的时候告诉我只能存String类型的数据,突然觉得这样的设计很不好
            如果能在存储的时候告诉我能存储哪些数据类型就好了。
            就像数组这样:
                String[] arr = new String[3];
                arr[0] = "hello";
              //arr[1] = 20;--不能存储
            java中集合就模仿着数组,也有了这样的做法,在创建集合的时候,就明确了
            元素的数据类型,创建后,再往集合中加入的元素的时候,只能是定义好的数据类型相关的
            数据了,然后再向下转型就没有问题了。
            这样的技术,java中叫做:泛型

            泛型:
                把明确数据类型的工作,提前到了编译时期,在创建集合的时候明确数据类型。
                这样的做法有点像把数据类型当作参数一样进行传递。所以泛型还有一个名字
                叫做:参数化类型。

           定义格式:  
                <引用数据类型>
                注意:尖括号中的数据类型只能是引用数据类型

           泛型的好处:
                1、将我们之前运行时候出现的问题,提前到了编译时期
                2、不需要强制类型转换了
                3、优化了代码,消除不必要的黄色警告线

           通过观察API发现,泛型可以出现了类,接口,方法上,看到一些类似与<E>,一般来说泛型
           出现在大多使用集合中。
*/

public class GenericDemo1 {
    public static void main(String[] args) {
        //创建List集合对象        
        //报错之后,在创建集合的时候加入泛型,明确集合的数据类型
        //赋值号右边的尖括号里可以不写,因为JDK1.7之后会自动进行类型推断
        ArrayList<String> list = new ArrayList<String>();

        list.add("hello");
        //添加泛型之后就不能存放Integer类型了
        //list.add(10);  //向上转型 10 --> int --> Integer
        list.add("world");
        list.add("java");
        list.add("bigdata");

        //获取迭代器对象--也要加泛型
        Iterator<String> iterator = list.iterator();

        while (iterator.hasNext()) {
          //加入泛型之后就不需要进行强转了,因为类型已经明确下来了
            String next = iterator.next();
            System.out.println(next + "--" + next.length());
          //加入泛型之前:
//            Object next = iterator.next();
          //ClassCastException:类型转换异常
//            String s = (String)next;
//            System.out.println(s);
        }
    }
}

泛型应用 

  • 泛型类

/*
        泛型类:  把泛型定义在类上
        格式:public class 类名<泛型类型1,…>
        注意:泛型类型必须是引用类型

        这里的<>里面的内容仅仅表示的是一种参数数据类型,参数类型是一种变量,
        既然是一种变量,就符合变量的命名规则,可以是任意符合标识符起名规则的名字。
*/
public class GenericTool1<T> {
    private T obj;

    public T getObj() {
        return obj;
    }

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

import com.shujia.wyh.day22.Student;

/*
        泛型类的测试
*/

public class GenericTest1 {
    public static void main(String[] args) {
        //不加泛型不会报错,默认是Object类型
//        GenericTool1 gt1 = new GenericTool1();
        //默认是Object类型的时候,我传入什么类型的值都可以
//        gt1.setObj("hello");
//        gt1.setObj(20);
//        gt1.setObj(12.34);
//        gt1.setObj(new Student());

      //加了泛型之后:
        GenericTool1<String> gt2 = new GenericTool1<>();
        gt2.setObj("hello");
      //加了泛型并明确了类型为String类型的时候
      //传入String类型之外的类型就会报错
//      gt2.setObj(20);

      //明确了String类型之后,返回值就是String类型
        String obj = gt2.getObj();
    }
}
  • 泛型方法

/*
        泛型方法
            把泛型定义在方法上
            格式:public <泛型类型> 返回类型 方法名(泛型类型 .)
*/
public class GenericTool2 <T>{//-第一种方式:在类中指定泛型
      //没有加入泛型的时候
//    public void show(String s){
//        System.out.println(s);
//    }
//
//    public void show(int i){
//        System.out.println(i);
//    }
//
//    public void show(double d){
//        System.out.println(d);
//    }

  //第一种方式:在类中指定泛型,在参数列表里面使用泛型
  //  public void show(T t){
  //      System.out.println(t);
  //  }
  
  //第二种方式:不在类中指定泛型
  //而是在方法中指定泛型
    public <T> void show(T t){
      System.out.println(t);
    }
}

import com.shujia.wyh.day22.Student;

/*
        泛型方法的使用
*/

public class GenericTest2 {
    public static void main(String[] args) {
      //没有加入泛型的时候每次想要传入一个新的数据类型
      //都要重载一遍show()方法
//        GenericTool2 gt1 = new GenericTool2();
//        gt1.show(10);
//        gt1.show("hello");
//        gt1.show(12.34);
      
//----------用泛型方法第一种方式改进之后--------
//        gt1.show(new Student());
      
      //创建泛型类对象--此时show()方法中只能传入在初始化泛型类时被声明的数据类型
//        GenericTool2<String> gt2 = new GenericTool2<>();
//        gt2.show("hello");
      //不能传入int类型
//        //gt2.show(20);
      
      //那想要传入Integer类型怎么办呢?只能再创建一个泛型类的对象
//        GenericTool2<Integer> gt3 = new GenericTool2<>();
//        gt3.show(20);
//
        //到目前为止,如果你能看懂,说明泛型类你是可以掌握的
        //但是有个问题,谁规定了方法的参数类型一定要和类的类型一致呢?
        //如果类上面没有泛型的话,方法还能不能随便传参呢?--可以

      
//--------用泛型方法第二种方式改进之后--------
      
       //创建对象
        GenericTool2 gt = new GenericTool2();
       //可以放入任何一种数据类型
        gt.show("hello");
        gt.show(20);
        gt.show(true);
    }
}
  •  泛型接口 

/*
 泛型接口
*/

public interface GenericTool3<T> {
    public abstract void show(T t);
}

//将来开发中实现接口的类名字后面加上Impl,易于区分
//实现泛型接口的类的类名后面也要加上<T>
public class GenericTool3Impl<T> implements GenericTool3<T>{
    @Override
    public void show(T t) {
        System.out.println(t);
    }
}

/*
        泛型接口的测试
*/

public class GenericTest3 {
    public static void main(String[] args) {
      //创建实现接口的类的对象
        GenericTool3Impl<String> sgt1 = new GenericTool3Impl<>();
        sgt1.show("hello");
    }
}

 泛型高级(通配符)

public class Animal {
}

public class Dog extends Animal {
}

public class Cat extends Animal {
}

import java.util.ArrayList;

/*
    泛型通配符<?>
        任意类型,如果没有明确,那么就是Object以及任意的Java类了
    ? extends E
        向下限定,E及其子类
    ? super E
        向上限定,E及其父类
*/

public class GenericDemo2 {
    public static void main(String[] args) {
        //如果泛型里面的类型只用一个,并且明确数据类型的时候,前后必须要写一致
        ArrayList<Animal> list1 = new ArrayList<Animal>();
        ArrayList<Dog> list2 = new ArrayList<Dog>();
        ArrayList<Object> list3 = new ArrayList<Object>();

        //泛型通配符<?>
        //任意类型,如果没有明确,那么就是Object以及任意的Java类了
        ArrayList<?> objects1 = new ArrayList<Animal>();
        ArrayList<?> objects2 = new ArrayList<Dog>();
        ArrayList<?> objects3 = new ArrayList<Object>();

        // ? extends E  向下限定,E及其子类
        ArrayList<? extends Animal> list4 = new ArrayList<Animal>();
        ArrayList<? extends Animal> list5 = new ArrayList<Dog>();
        ArrayList<? extends Animal> list6 = new ArrayList<Cat>();
        //向下限定,只能传入E及其子类,不能是E的父类
        //ArrayList<? extends Animal> list7 = new ArrayList<Object>();

        // ? super E  向上限定,E及其父类
        ArrayList<? super Animal> list7 = new ArrayList<Animal>();
        ArrayList<? super Animal> list8 = new ArrayList<Object>();
        //向上限定,只能传入E及其父类,不能是E的子类
        //ArrayList<? super Animal> list9 = new ArrayList<Dog>();
    }
}
上一篇:微信小程序加水印(含代码)


下一篇:android动态权限适配:基于RxJava2后的RxPermissions的快速使用