泛型

泛型:

是种未知的数据类型,当我们不知道使用什么数据类型的时候可以使用泛型,泛型也可以看出是一个变量用来接收数据类型。

E e: Element元素

Tt Type类型

ArrayList集合在定义的时候不知道集合中都会存储什么类型的数据,所以类型使用泛

型E未知的数据类型。

1.泛型的好处

创建集合对象,不用泛型

好处:

  • 默认Object类型,可以存储任意类型的数据

弊端:

  • 不安全,可能会导致类型转换异常。ClassCastException

    调用子类特有的方法,向下转型 String s=(String)next; System.out.println(s.length());

    Integer类型无法转换为String类型

package setclass.Collection;

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

public class TestDemo {
  public static void main(String[] args) {
      ArrayList list=new ArrayList();
      list.add("张三");
      list.add(1);
      list.add(true);
      Iterator it = list.iterator();
      while (it.hasNext()){
          Object next = it.next();
          System.out.println(next);
          //调用子类特有的方法,向下转型
          String s=(String)next;
          System.out.println(s.length());
      }
  }
}

创建集合对象,使用泛型

好处:

  • 避免类型转换异常的麻烦,可以存储设什么类型的数据就取出什么类型

  • 将运行期异常提升到编译期类型

弊端:

  • 只能存储一种类型

private static void demo2() {
  ArrayList<String> list=new ArrayList<>();
  list.add("张三");
  list.add("李四");
  list.add("王五");
  Iterator<String> it = list.iterator();
  while (it.hasNext()){
      String next = it.next();
      System.out.println(next);
      System.out.println(next.length());
  }
}

2.定义和使用含有泛型的类

含有泛型的类:

  • 泛型类,模拟ArrayList集合

  • 泛型可以接受未知的数据类型,创建对象时确定泛型数据类型

package setclass.Genericdemo;

public class GenericClassDemo<E> {//泛型类,模拟ArrayList集合
      //泛型可以接受未知的数据类型,创建对象时确定泛型数据类型
  private E name;//E 表示未知数据类型

  public E getName() {
      return name;
  }

  public void setName(E name) {
      this.name = name;
  }
}

测试类:

  • 默认Object类型

    GenericClassDemo gcd = new GenericClassDemo();
  • 泛型使用String类型

    GenericClassDemo< String > gc = new GenericClassDemo<>();
  • 泛型使用Integer类型

    GenericClassDemo< Integer > gc1 = new GenericClassDemo<>();
package setclass.Genericdemo;

public class GenericTestDemo1 {//测试类

  public static void main(String[] args) {
      //默认Object类型
      GenericClassDemo gcd = new GenericClassDemo();
      //泛型使用String类型
      GenericClassDemo<String> gc = new GenericClassDemo<>();
      gc.setName("张三");
      System.out.println(gc.getName());
      //泛型使用Integer类型
      GenericClassDemo<Integer> gc1 = new GenericClassDemo<>();
      gc1.setName(100);
      System.out.println(gc1.getName());
   
  }
}

3.定义含有泛型的方法

格式:

修饰符 泛型 返回值类型 方法名(参数列表){

方法体

}

传递什么类型的数据,泛型就是什么数据。 也可以定义含有泛型的静态方法。

package setclass.Genericdemo;

public class GenericMethod {//含有泛型的测试方法
  public <E> void gcMethod(E e){
      System.out.println(e);
  }
}

测试:

GenericMethod gc = new GenericMethod();
gc.gcMethod(10);
运行结果:
10

4.含有泛型的接口

一种在实现接口时,确定泛型的类型;

另一种是在创建对象时,确定泛型的类型。

4.1第一种使用方式:定义接口的实现类,实现接口,指定接口的泛型

迭代器接口:

public interface Iterator< E> {

E next();

Scanner类实现了Iterator接口,并指定接口的泛型为String,所以重写的next方法泛型默认就是String

public final class Scanner implements Iterator< String>{

public String next() { }

}

泛型接口:

public interface GenericInterface<I> { //定义泛型接口
void method(I i);//抽象方法 method,默认public abstract
}

通过实现类,实现接口,指定接口的泛型:

public class GenericInterfaceImp1 implements GenericInterface<String>{//定义实现类
//通过实现接口,指定接口的泛型
@Override
public void method(String s) {
System.out.println(s);
}


}

测试类

public class GenericInterfaceTestDemo {
public static void main(String[] args) {//测试含有泛型的接口
GenericInterfaceImp1 gci1 = new GenericInterfaceImp1();
gci1.method("潜龙");
}
}
潜龙
4.2第二种使用方式:接口使用什么泛型,实现类就使用什么泛型,类跟着接口走

就相当于定义了一一个含有泛型的类,创建对象的时候确定泛型的类型

public interface List< E>{ boolean add(E e); E get(int index); }

ArrList实现List接口:

public class Arraylist< E> implements list< E>{ public boolean add(E e) {} public E get(int index) {} }

接口使用什么泛型,实现类就使用什么泛型,类跟着接口走:

public class GenericInterfaceImp2<I> implements GenericInterface<I>{
@Override
public void method(I i) {
System.out.println(i);
}
}

测试类

public class GenericInterfaceTestDemo {
public static void main(String[] args) {//测试含有泛型的接口
GenericInterfaceImp2<String> gci2 = new GenericInterfaceImp2<>();
gci2.method("张三");
GenericInterfaceImp2<Integer> gci21 = new GenericInterfaceImp2<>();
gci21.method(123);
}
}
运行结果:
潜龙
张三
123

5.泛型的通配符

泛型的通配符:

?:代表任意的数据类型

使用方式:

  • 不能创建对象使用

  • 只能作为方法的参数使用

遍历含有多个数据类型的集合时,用含有泛型通配符的参数的方法遍历,使用迭代器遍历,迭代器返回的为Object类型的数据。

  • 泛型没有继承概念。

package setclass.Genericdemo;

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

public class Demo1Generic {//泛型通配符
public static void main(String[] args) {
ArrayList<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(2);
list1.add(3);
list1.add(4);
ArrayList<String> list2=new ArrayList<>();
list2.add("zhangsan");
list2.add("刘四");
list2.add("张三");
printArray(list1);
printArray(list2);
}
public static void printArray(ArrayList<?> list){
Iterator<?> it = list.iterator();
while (it.hasNext()){
Object next = it.next();
System.out.println(next);
}
}
}
运行结果:
1
2
3
4
zhangsan
刘四
张三
泛型通配符高级使用
  • 泛型的上限限定: ? extends E

代表使用的泛型只能是E类型的子类/本身

  • 泛型的下限限定: ? super E

代表使用的泛型只能是E类型的父类/本身

 

通过extends限制了通配符的上边界,也就是只接受Number及其子类类型。接口的实现和类的集成都可以通过extends来表示。

而这里的Number也可以替换为T,表示该通配符所代表的类型是T类型的子类。

public static void getData(List<? extends T> data) {
System.out.println("data :" + data.get(0));
}

与上界通配符示对照也有下界通配符:

public static void getData(List<? super Integer> data) {

System.out.println("data :" + data.get(0));

}

下界通配符表示该通配符所代表的类型是T类型的父类。
posted @ 2021-09-12 17:10  晚风将至  阅读(40)  评论(0编辑  收藏  举报