Java教程

Java中对泛型的理解及应用

本文主要是介绍Java中对泛型的理解及应用,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

泛型

概念:是一个未知的数据类型,是一个参数化类型

使用场景:

  • 如果需要给一个类型定义属性,但是这个类型中的属性不确定,可以使用泛型来代替定义。
  • 如果需要定义一个方法,但是该方法的参数列表类型和返回值类型不确定,可以使用泛型来定义。

泛型类 的定义与使用

在定义类型时,类上有泛型的使用,那么该类就是泛型类

格式:

class 类名<泛型>{  
   
} 

class person<T>{
    private T name;
    }

注意事项:

  • 如果想要在类中使用泛型,首先需要在类的声明上,声明该泛型符号

  • 如何定义泛型:

    • 泛型符号可以是任意标识符
    • 但是一般使用大写的字母来表示 M T Q L
  • 如果一个类型定义了泛型,在使用这个类型的时候,可以确定泛型也可以不确定泛型。

    • 如果不确定泛型的话:默认使用Object来接收参数

    • 如果确定了泛型:那么就只能使用确定的类型来接收参数

  • 在确定泛型的时候,泛型前后要一致

    • 后面的泛型类型可以不写,因为可以根据泛型推断,将后面的类型会默认和前面保持一致。但是<>不能省略。
  • 可以在一个类中使用多个不同的泛型,使用几种就需要声明几种

  • 在使用类型时,如果类型声明了多个泛型,要么一个都不指定,要么全都指定

**好处:**可以提高类型的扩展性

代码:

public void main(String[] args) {
        person p = new person();
        p.name = 180.2;
        p.age = "453";

        person<String, Integer> p1 = new person<>();
        p1.name = "chen";
        p1.age = 11;

        person<Double,Boolean> p2 = new person<>();
        p2.name = 18.5;
        p2.age = true;
    }
    class person<T,M>{
        T name;
        M age;
    }

泛型方法 的定义和使用

使用泛型定义的方法

格式:

修饰符 <泛型的声明> 返回值类型 方法名(){
	} 

注意事项:

  • 如果定义了一个静态方法,该静态方法中需要使用泛型,那么**静态方法只能自己先声明,后使用。**不能使用类上声明的泛型。
public void main(String[] args) {		
		printValue("chen");
        printValue(124);     //默认转换成Integer类型、只能是引用类型
    }
    //定义了一个静态方法,必须先声明泛型
    public static <T> void printValue(T t){
        System.out.println(t);
    }
  • 如果定义了一个非静态方法,该方法既可以使用类上声明的泛型,也可以自己声明泛型。
public class E <L>{
    public void main(String[] args) {
        E e = new E();
        e.printValue1(11);
    }
//可以在类上声明   
public void printValue1(L l){
        System.out.println(l);
    }
//也可以自己声明 
public <L> void printValue1(L l){
        System.out.println(l);
    }
  • 方法中如果需要声明泛型,也可以同时声明多个泛型
public void main(String[] args) {
	printValue2("chen",22);
    }
    public static <P,M> void printValue2(P t,M m){
        System.out.println(t);
        System.out.println(m);
    }

泛型接口 的定义和使用

概述:如果接口中的抽象方法需要使用泛型,也需要先在接口上声明该泛型

注意:

  • 将来接口的实现类如果实现了接口,但是没有指定泛型类型,在实现类中默认使用Object来表示该泛型。
//接口中应用泛型
public interface A <T,M>{
    public T get();
    public void set(M m);
}
//实现类实现该接口
public class elemA implements A{

    @Override
    public Object get() {    //默认Object类型
        return null;
    }

    @Override
    public void set(Object o) {

    }
}
  • 实现类实现接口之后,如果需要使用该泛型,就要在实现接口时,就要指定该泛型的类型,指定的类型是谁, 就使用谁。
//接口中应用泛型
public interface A <T,M>{
    public T get();
    public void set(M m);
}
//实现类实现该接口
public class elemA implements A<String,Integer>{
    @Override
    public String get() {
        return null;
    }
    @Override
    public void set(Integer integer) {

    }
}

  • 如果实现类实现接口之后,没有指定泛型,也需要使用这个泛型符号,只能在实现类中也声明该泛型。
//接口中应用泛型
public interface A <T,M>{
    public T get();
    public void set(M m);
}
//实现类实现该接口,泛型不指定,需要在类名后声明
public class elemA <T,M> implements A<T,M>{
    @Override
    public T get() {
        return null;
    }

    @Override
    public void set(M m) {

    }
}

泛型 集合对泛型的使用

概述:学习的集合是支持泛型的

​ 可以使用泛型,也可以不使用泛型

如果定义集合之后,没有使用泛型:元素在集合中都是Object接收

如果定义集合之后,使用了泛型,元素在集合中就是定义的类型

public class Arraylist_E <T> {
    ArrayList<T> a = new ArrayList<>();
}

泛型定义集合的特点

  • 如果定义的集合使用了泛型,那么当前集合中只能添加对应类型的元素;
  • 使用集合元素特有的方法时,不需要向下转型,直接使用即可

集合遍历的总结

  • 使用迭代器或者增强for循环遍历集合时,因为集合制定了确切的泛型类型,所以在使用集合的元素时不需要再向下转型
 //增强for循环遍历
        for (String o:a){
            System.out.println(o);  //不用向下转型
        }

        //迭代器遍历
        ListIterator<String> it = a.listIterator();
        while (it.hasNext()){
            String s =it.next();      //不用向下转型
            System.out.println(s);
        }
  • 使用转数组:toArray方法遍历的时候,该方法的返回值固定是Object类型

    所以使用元素的特殊方法时,也需要向下转型。

  • 但是转数组,有另外一种方式:toArray(T[] arr)

    在转数组的时候,可以自主准备一个数组,用来存储元素,数组可以和数据的类 型保持一致,那么在转换之后也不需要向下转型。

    • 如果准备的数组空间正好够存,或者空间多余元素,那么可以转移到自己的数组中。
    • 如果准备的数组空间不够存储元素,该方法会返回一个新数组用来存储数据。
//转数组遍历
        String[] strs = new String[a.size()];
        for (int i = 0; i < strs.length; i++) {
            String s = strs[i];
            System.out.println(s);
        }

泛型 的通配符

概述:将来定义数据类型时,如果这个数据类型不确定,可以使用泛型来表示这个不确 定的类型;也可以使用泛型通配符来定义这个不确定的类型。

分类:

  • ?:泛型的通配符 可以表示任何泛型
  public static void main(String[] args) {
        ArrayList<Object> list1 = new ArrayList<>();
        ArrayList<Integer> list2 = new ArrayList<>();
        ArrayList<Number> list3 = new ArrayList<>();
        ArrayList<String> list4 = new ArrayList<>();
      
        getList1(list1);
        getList1(list2);
        getList1(list3);
        getList1(list4); 
      
  public static void getList1(ArrayList<?> list){
      } 
//都可以 
  • ? extends E: 泛型通配符 可以表示泛型E类型或者泛型E类型子类类型
  public static void main(String[] args) {
        ArrayList<Object> list1 = new ArrayList<>();
        ArrayList<Integer> list2 = new ArrayList<>();
        ArrayList<Number> list3 = new ArrayList<>();
        ArrayList<String> list4 = new ArrayList<>();
      
        getList2(list1);   //Object   不行
        getList2(list2);   //Integer  可以
        getList2(list3);   //Number   可以
        getList2(list4);   //String   不行
     
      //? extends Number:表示可以接收Number类型或者Number子类类型
   public static void getList2(ArrayList<? extends Number> list){
    }
  • ? super E: 泛型通配符 可以表示泛型E类型或者泛型E类型的父类类型
  public static void main(String[] args) {
        ArrayList<Object> list1 = new ArrayList<>();
        ArrayList<Integer> list2 = new ArrayList<>();
        ArrayList<Number> list3 = new ArrayList<>();
        ArrayList<String> list4 = new ArrayList<>();
      
        getList3(list1);    //Object  可以
        getList3(list2);    //Integer 不行
        getList3(list3);    //Number  可以
        getList3(list4);    //String  不行
      
      //? super Number:表示可以接收Number类型或者Number父类类型
    public static void getList3(ArrayList<? super Number> list){
    }
这篇关于Java中对泛型的理解及应用的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!