0%

java-Day11——泛型

泛型的引入

所谓泛型,就是允许在定义类、接口时通过一个标识来表示类中某个属性的类型或者是某个方法的返回值或参数的类型。这个类型参数将在使用时(例如,继承或实现这个接口、创建对象或调用方法时)确定(即传入实际的类型参数,也称为类型实参)

在集合使用泛型前可能存在的问题

问题1:类型不安全。因为add()的参数是Object类型,意味着任何类型的对象都可以添加成功

问题2:需要使用强转操作,繁琐。还有可能导致ClassCastException异常

泛型的使用

使用说明

  • 集合框架在生命接口和实现类时使用泛型,在实例化集合对象时,如果没有使用泛型,则认为操作的是Object类型的数据。如果使用了泛型,则需要指明泛型的具体类型。一旦指明了泛型的具体类型,则阿紫集合的相关的方法中,凡是使用泛型的位置,都替换为具体的泛型类型。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class GenericTest {
@Test
public void test(){
List<Integer> list = new ArrayList<Integer>();
list.add(78);
list.add(254);
list.add(54);
list.add(99);
//编译报错,保证类型安全
// list.add("AA");
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()){
//因为添加的都是Integer类型,避免了强转操作
Integer i = iterator.next();
int score = i;
System.out.println(score);
}
}
//在map中的使用
@Test
public void test2(){
HashMap<String, Integer> map = new HashMap<>();//类型推断
map.put("Tom", 12);
map.put("jack",23);
map.put("hh", 24);

Set<Map.Entry<String, Integer>> entreSet = map.entrySet();
Iterator<Map.Entry<String, Integer>> iterator = entreSet.iterator();

while (iterator.hasNext()){
Map.Entry<String, Integer> entry = iterator.next();
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key+"-->"+value);
}
}
}

自定义泛型

自定义泛型类\接口

格式

class A{

}

interface B<T1,T2>{

}

使用说明:

  1. 声明完自定义泛型类以后,可以在类的内部(比如属性、方法、构造器中)使用类的泛型
  2. 创建自定义泛型类的对象时,可以指明泛型参数类型。一旦指明,内部凡是所使用类的泛型参数的位置,都具体化为指定的类的泛型类型。
  3. 创建自定义泛型类的对象时,没有指明泛型参数类型,那么泛型将被擦除,泛型对应的类型均安装Object处理,但不等于Object。经验:泛型要用使用一路都用,要不用,一路都不用。
  4. 泛型的指定中必须使用引用数据类型。不能使用基本数据类型,此时只能使用包装类替换。
  5. 除创建泛型类对象外,子类继承泛型类时、实现类实现泛型接口时,也可以确定泛型结构中的泛型参数。

如果我们在给泛型类提供子类时,子类也不确定泛型的类型,则可以继续使用泛型参数。

我们还可以再现有的父类的泛型参数的基础上,新增泛型参数

注意:

  1. 泛型类可能有多个参数,此时应将多个参数一起放在尖括号内。比如<E1,E2,E3>

  2. JDK7开始,泛型的简化操作:ArrayList flist = new ArrayList<>();

  3. 如果泛型结构是一个接口或抽象类,则不可以创建泛型类的对象

  4. 不能使用new E()。但是可以,E[] elements = (E[])new Object[capacity];

  5. 在类/接口上声明的泛型,在本类或本接口中即代表某种类型,但不可以在静态方法中使用类的泛型。

  6. 异常类不可以带泛型。

自定义泛型方法

格式

权限修饰符 返回值类型 方法名(形参列表){

}

举例

public E method(E e){

}

说明

  • 声明泛型方法时,一定要添加泛型参数
  • 泛型参数在方法调用时,指明其具体的类型
  • 泛型方法可以根据需要声明为static
  • 泛型方法所属的类是否是一个泛型类,都可以。

泛型在继承上的体现

1.类SuperA是类A的父类,则G与G的关系?

二者是并列的两个类,没有任何子父类的关系

2.类SuperA是类A的父类或接口,superA与A的关系?

superA与A有继承或实现的关系。即A的实例可以赋值给SuperA类型的引用或变量。

通配符

使用说明

ArrayList<?>

G 可以看作是G类型的父类,即可以将G的对象赋值给G类型的引用或变量

读写特点

  • 读取数据:允许的,读取的值为Object类型
  • 写入数据:不允许。特例,null

有限制条件的通配符

List<? extends A>:可以将List或List赋值给List<? extends A>其中B类是A类的子类

List<? super A>:可以将List或List赋值给List<? super A>其中B类是A类的父类

常见问题

Java的泛型是什么?有什么好处和优点?JDK不同版本的泛型有什么区别?

泛型,是程序中出现的不确定的类型。

以集合来举例:把一个集合中的内容限制为一个特定的数据类型,这就是generic背后的核心思想。

-------------本文结束感谢您的阅读-------------