一、初识泛型

在推出泛型以前,程序员可以创建一个元素类型Object的集合,该集合能够存储任意的数据类型对象,而在使用该集合的过程中,需要明确知道存储每个元素的类型,否则容易引发ClassCastException异常。

泛型是JDK1.5引入的新语法,通俗讲,泛型:就是适用于许多许多类型。从代码讲,就是对类型实现了参数化

JAVA为什么推出泛型?

当Integer类型转换成String型时,会发生类型转换错误,并且编译时不会发生错误,很容易项目上线时,发生报错,为了应对这种情况,推出了泛型。

泛型的概念?

Java泛型时JDK5引入的一个新特性,泛型提供了编译时类型安全监测机制,该机制允许我们编译时检测到非法的类型数据结构

泛型的优点?

1.编译时,类型检查

2.编译时,类型转换

注意:泛型只存在编译时,运行时不存在泛型这个概念,同时泛型只能接收包装类型,不能接受普通类型

实现了一类,类中包含了一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中某个下标的值

二、泛型类、接口

泛型类的语法

  Generic.java

package demo;
/*
@param<T>泛型标识————类型形参
       T 创建对象的时候里指定具体的数据类型
*/

public class Generic<T>
{
    private T key;
    public Generic(T key)
    {
        this.key = key;
    }

    public T getKey() {
        return key;
    }

    public void setKey(T key) {
        this.key = key;
    }

    @Override
    public String toString() {
        return "Generic{" +
                "key=" + key +
                '}';
    }
}

  MainClass.java

public class MainClass {
    public static void main(String[] args) {
        //泛型类在创建对象的时候,来具体类型
        Generic<String> strGeneric = new Generic("a");
        String k1 = strGeneric.getKey();
        System.out.println(k1);

        System.out.println("---------------------------------");
        Generic<Integer> integerGeneric = new Generic<>(123123213);
        int key2 = integerGeneric.getKey();
        System.out.println(key2);

        System.out.println("-------------------------");
        Generic gen = new Generic();//"当我们不对其使用泛型指定类型时,里面可存储的值可以为类型类型"
    }
}f

注意:

泛型不支持基本数据类型,只支持类类型

引用类型无法通过大于和小于进行比较

泛型类型逻辑上可以看作不同类型,实际上都是相同类型

三、泛型的接口

泛型接口的定义语法

Interface 接口名称<泛型标识,泛型标识,...>{

泛型标识 方法名();

}

实现泛型接口的类,不是泛型类,需要明确实现泛型接口的数据类型。

四、泛型方法

前面我们知道,泛型类,是在实例化类的时候指明泛型的具体类型;而泛型方法,是在调用方法的时候指明泛型的具体类型。

最重要的一点我们之前使用的方法,其实只是实参是泛型参数的普通方法,并不叫做泛型方法。


public class xx<T>
{
private T key;
Public T setKey(T key)
{
  this.key = key;
} 
Public T getKey()
{
  return key;
  }
}

定义一个泛型方法需要在返回值前面定义一个<>,里面填入泛型参数,T E ... 等等泛型参数

Public 与返回键中间<T>非常重要,可以理解为声明此方法为泛型方法

只有声明了<T>的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。

<T>表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T

泛型方法与可变参数

为什么静态方法访问不了类上的泛型参数

这是因为,我们在指定泛型参数的具体类型时,是在实例化该类时指定的,实例化后和类型有关,所以静态方法和静态属性访问 泛型参数,必须在static后添加<T,E......>

五、类型通配符

类型通配符一般是使用”?“代替具体实参类型

所以,类型通配符是类型实参,而不是类型形参。

  Box.java


  package Demo01;
  public class Box<E> {
      private E first;
      public E getFirst() {
          return first;
      }
      public void setFirst(E first) {
          this.first = first;
      }
  }

  Test.java


package Demo01;
public class Test {
    public static void main(String[] args) {
        Box<Number> box1= new Box<>();
        box1.setFirst(100);
        showBox(box1);
        Box<Integer> box2 = new Box<>();
        box2.setFirst(200);
        showBox(box2);
    }
    public static void showBox(Box<?> box)
    {
        Object first = box.getFirst();
        System.out.println(first);
    }
}

六、类型擦除

编译阶段,编译器会进行类型检测, 一旦通过编译检测,进入运行阶段,此时泛型这个概念就会消失,通常我们说的,泛型只停留在编译阶段就是这个道理,所有的对象都属于普通类,所以下面这段代码的运行结果为true.

类型参数带来了许多弊端

①、不支持基本类型

②、只有原始类型class

③、不能实例化类型参数

④、不能实例化泛型数组

七、类型的上界

这个地方意味着T必须实现他的上界Comparabe<T>接口
class Alg<T extends Comparable<T>>
{
    public T findMax(T[] array){
        T max = array[0];
        for (int i = 0; i < array.length; i++) {
            if(max.compareTo(array[i]) < 0)
            {
                max = array[i];
            }
        }
        return max;
    }

}
public class Test {
    public static void main(String[] args) {
        Alg<Integer> alg = new Alg<>();
        Integer[] array = {1,5,2,7,19,4};
        Integer max = alg.findMax(array);
        System.out.println(max);
    }
}

Logo

为武汉地区的开发者提供学习、交流和合作的平台。社区聚集了众多技术爱好者和专业人士,涵盖了多个领域,包括人工智能、大数据、云计算、区块链等。社区定期举办技术分享、培训和活动,为开发者提供更多的学习和交流机会。

更多推荐