Java——泛型


前言

泛型:可以在类或方法中预先地使用未知的类型。
tips:一般在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为Object类型。


提示:以下是本篇文章正文内容,下面案例可供参考

一、泛型定义

在类/接口定义:
语法: public class/interface 类名<泛型变量1[,泛型变量2....]>

使用范围: 泛型变量作为属性的数据类型, 泛型变量作为构造方法的参数的数据类型, 泛型变量作为普通方法的返回值数据类型, 参数的数据类型

在方法上定义: 可以是静态方法,也可以是普通方法

语法: 访问修饰符 <泛型变量1[,泛型变量2....]> 返回值类型/泛型变量 方法名(参数数据类型/泛型变量 参数名)

使用范围: 泛型变量作为定义它的方法的返回值数据类型, 参数的数据类型

静态方法不能使用类定义的泛型变量

/**
 * 为什么要使用泛型
 *   没有使用泛型: 带来那些不好的
 *
 *   没有使用泛型:
 *      优点: 集合可以存储任意数据类型的元素
 *      缺点: 1. 集合无法限制元素的类型
 *           2. 获取元素,得到都是Object类型, 需要向下转型, 可能出现ClassCastException的异常
 */
public class Demo1 {
    public static void main(String[] args) {
        //添加任意数据类型的元素
        List list = new ArrayList();
        list.add("hello"); //String   向上转型,  Object
        list.add(123); //Integer  向上转型,  Object
        list.add(new Student(1,"张三")); //Student  向上转型,  Object

        //获取元素  Object get(下标), 遍历得到元素,  元素的类型: Object
        Object ele = list.get(1);
        if(ele instanceof  String){
            //需要进行向下转型
            String str = (String) ele; //ClassCastException
        }else if((ele instanceof  Integer){
            int i = (Integer) ele;
        }
    }

}
什么是泛型:   参数化类型, 通俗易懂:  把数据类型作为参数, 在创建类, 把数据类型作为一个参数传递给类,

 >声明一个数据类型的变量:
 >
 >语法:  <变量名>         
 >
 >泛型变量在类/接口上       泛型类
 >
 >public class 类名<泛型变量名>{  //泛型变量名可以在类属性,方法,构造方法上使用
 >
 >}
 >
 >泛型变量:  默认的值: Object
 >
 >给泛型变量赋值:   在创建泛型类的对象时给泛型变量赋值:   
 >
 >泛型变量:  类类型数据类型, 不能使用基本数据类型
 >
 >语法:   类名<类类型数据类型>  对象名 = new 类名<类类型数据类型>()
>定义泛型变量, 推荐大写, 就一个字母:   推荐的名字: T(type), K(key的数据类型),V(value的数据类型), E(element元素的数据类型)

>类上的泛型变量:
>
>注意:
>
>    1. 只能在类的属性上, 非静态方法的,构造方法上使用,不能再static的资源使用
>
>    2. 如果想在static方法上使用泛型变量,   那这个泛型变量只能在方法上声明, 
//静态方法
    public static <E> E fun3(){
        return null;
   }
3. 如果在方法上定义泛型变量,  这个泛型变量的赋值, 不是显示赋值, 如果泛型方法参数使用泛型变量,就是传递给方法的值的数据类型, 作为泛型变量的值 隐式赋值

4. 泛型方法的参数没有使用泛型变量,  是在调用这个方法, 使用变量接收这个方法的返回值, 接收返回值变量的数据类型, 作为泛型变量的值  这种方式,基本不使用

在这里插入图片描述

二、使用泛型

如果是使用泛型类/接口, 创建泛型类/接口的对象的时候, 类名/接口名<具体的数据类型>

泛型变量只能接收类类型,不能接收基本数据类型, 对于基本数据类型, 写的它的包装类

int (错误) --> Integer(对)

List<String> list = new ArrayList<String>(); //后面的实现类的泛型变量值与等号左边的泛型变量值一样
List<Object> list = new ArrayList<String>(); //错误的, 泛型中,没有泛型继承

在jdk1.7之后, =右边的泛型赋值可以省略,但是<>不能省略
List<String> list = new ArrayList<>();

使用泛型的优点:

  1. 限制了集合中元素的类型

  2. 获取元素的时候,不需要进行向下转型, 获取就是存储的类型

 public static void main(String[] args) {
        //使用泛型   list1集合中只能存储String类型的数据
       List<String>  list1 = new ArrayList<>();
       //list1.add(111);//错误, 只能添加String
        list1.add("hello");
        list1.add("world");

        //2.获取集合的元素
        String str = list1.get(1);

    }

如果是使用泛型方法: 不需要我们显示的赋值, 如果这个泛型变量作为参数的数据类型, 泛型变量的值为给参数赋值的数据类型.

public class GenericDemo2 {
    //泛型方法
    public static <T>  T fun1(T a){
        return a;
    }

    public static void main(String[] args) {
        //使用泛型方法
       String rs =  fun1("abc"); // T 跟传递的参数的值的数据类型一样
    }
}

三、 泛型通配符

当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示.但是一旦使用泛型的通配符后,只能使用Object类中的方法,集合中元素自身方法无法使用.

此时只能接收数据,获取元素,不能往该集合中存储数据

public class GenericDemo3 {

    public static void main(String[] args) {
        List<String> list1 = new ArrayList<>();
        list1.add("hello");
        list1.add("world");
        //List<Integer> list2 = new ArrayList<>();
        //List<Object> list3 = new ArrayList<>();

        print2(list1);
       // print2(list2);
       // print2(list3);
    }

    //定义一个方法, 打印List集合,  集合的元素任意数据类型
    //List没有泛型
    /*public static void print(List list){
        System.out.println("遍历集合:");
        for (Object o : list) {
            System.out.println(o);
        }
    }*/

    //定义泛型类型的List接收任意list   泛型变量的值不确定, 使用泛型通配符  ?
    //不能使用List<Object>, 因为泛型类不能继承
    public static void print2(List<?> list){
        System.out.println("遍历集合:");
        for (int i = 0; i< list.size();i++) {
            System.out.println(list.get(i));
        }

        //添加一个元素
        //list.add("aaa");
    }
}
f: 受限泛型

之前设置泛型的时候,实际上市可以设置任意类型的,只要是类就可以设置.但是在java的泛型中可以指定一个泛型的上限和下限.

泛型上限:

- 格式: `类型名称<? extends 类> 对象名称`

- 意义: 只能接收该类型及其子类

在这里插入图片描述

泛型下限:

- 格式:`类型名称<? super 类> 对象名称`

- 意义:只能接收该类型及其父类类型
 

在这里插入图片描述

/**
* 泛型上限:
* -  格式: `类型名称<? extends 类> 对象名称`
* - 意义: 只能接收该类型及其子类
*
* 泛型上限:
* - 格式:`类型名称<? super 类> 对象名称`
* - 意义:只能接收该类型及其父类类型
*/
public class GenericDemo {
  public static void main(String[] args) {
      List<Integer> list1 = new ArrayList<>();
      List<String> list2 = new ArrayList<>();
      List<Number> list3 = new ArrayList<>();
      List<Object> list4 = new ArrayList<>();

      fun1(list1);
      fun1(list2); //报错
      fun1(list3);
      fun1(list4); //报错

      fun2(list1); //报错
      fun2(list2); //报错
      fun2(list3);
      fun2(list4);

  }
  //泛型上限: 此时的泛型?,必须是Number类型或者Number类型的子类
  public static void fun1(List<? extends  Number> list){}
  //泛型下限: 此时的泛型?,必须是Number类型或者Number类型的父类
  public static void fun2(List<? super  Number> list){}
}

/**
 * 使用泛型遍历Map
 */
public class Demo2 {
    public static void main(String[] args) {
        //创建一个Map, key: String , value: Student
        Map<String,Student> studentMap = new HashMap<>();
        //添加数据
        studentMap.put("张三",new Student(1,"张三"));
        studentMap.put("李四",new Student(2,"李四"));

        //遍历Map   使用entrySet
        //Map.Entry<String,Student> 是Set的泛型变量的值
        //<String,Student> 是Entry的两个泛型变量的值
        Set<Map.Entry<String,Student>> entrys = studentMap.entrySet();
        //迭代器,增强for 遍历
        for(Map.Entry<String,Student> entry :entrys){
            String key = entry.getKey();
            Student stu = entry.getValue();
            System.out.println("key:"+key+"-->"+"value:"+stu);
        }

    }
}

四、Collections 集合帮助类/工具类

位于java.util包, 它的所有的方法都是static修饰的, 不需要创建对象,直接使用类名.方法名()调用

  >面试题:  Collection 与Collections区别
  >
  >Collection  是List,Set集合的父接口
  >
  >Collections 是集合的帮助类,  提供了对集合操作的方法,类似之前的Arrays

>public static <T> boolean  addAll(Collection<T> c, T... elements): 往集合中添加一些元素
>
>public static void shuffle(List<?> list): 打乱集合顺序
>
>public static <T> void sort(List<T> list): 将集合中元素按照默认规则排序
>
>public static <T> void sort(List<T> list,Comparator<? super T>): 将集合中元素按照指定规则排
/**
 * 集合帮助类: Collections
 */
public class CollectionsDemo1 {

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        //使用集合的add() 添加元素  一个一个添加
        /*list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");*/



        //常用的方法:
        //往Collection集合添加元素
        //static <T> boolean addAll(Collection<? super T> c, T... elements)
        Collections.addAll(list,"a","d","e","f","b");
        System.out.println(list);  //[a, b, c, d, e]

        //public static void shuffle(List<?> list): 打乱集合顺序
        List<String> list1 = new ArrayList<>();
        Collections.addAll(list1,"大王","小王","黑桃A","黑桃K","黑桃Q","黑桃J","黑桃10","黑桃9","黑桃8","黑桃7","黑桃6","黑桃5");
        System.out.println("洗牌前,牌的顺序:");
        System.out.println(list1);
        //打乱, 洗牌
        Collections.shuffle(list1);
        System.out.println("洗牌后,牌的顺序:");
        System.out.println(list1);


        //排序 public static <T> void sort(List<T> list): 将集合中元素按照默认规则排序    升序
        Collections.sort(list);
        System.out.println("排序之后,集合的顺序:");
        System.out.println(list);

        //List集合添加学生, 对学生排序   定义比较器:  类实现Comparable,
        List<Student> stuList = new ArrayList<>();
        stuList.add(new Student(1,"张三"));
        stuList.add(new Student(6,"王五"));
        stuList.add(new Student(4,"李四"));
        System.out.println("排序前:");
        System.out.println(stuList);

        //排序
       Collections.sort(stuList);

        System.out.println("排序后:");
        System.out.println(stuList);


        //指定比较强:
        // public static <T> void sort(List<T> list,Comparator<? super T>): 将集合中元素按照指定规则排序
        Collections.sort(stuList, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o2.getStuNo() - o1.getStuNo();
            }
        });

        System.out.println("排序后:");
        System.out.println(stuList);
    }
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值