6.6 泛型
6.6.1 反省概述
泛型是程序设计语言的一种特性。
在使用泛型的过程中,操作的数据类型被指定为一个参数,这种参数类型在类、接口和方法在、分别称为泛型类、泛型接口、泛型方法。相对于传统上的形参,反省可以使参数具有更多类型上的变化,使代码能够更好的复用。
6.6.2 泛型类和泛型对象
泛型类就是在类声明时通过一个标识表示类中某个属性的类型或者是某个方法的返回值和参数类型。只有用户使用该类的时候,该类所属的类型才能明确。
泛型类的声明格式具体如下:
[访问权限] class类名称<泛型类型标识1,泛型类型标识2,...,泛型类型标识n>
[访问权限] 泛型类型标识 变量名称;
[访问权限] 泛型类型标识 方法名称;
[访问权限] 返回值类型声明 方法名称(泛型类型标识 变量名称){};
定义好泛型之后,就可以创建泛型对象。创建泛型对象的语法格式具体如下:
类名称<参数化类型> 对象名称 = new 类名称<参数化类型> ();
案例学习6—22
import java.util.*;
public class Example22{
public static void main(String[] args) {
ArrayList list = new ArrayList();//创建ArrayList
list.add("String");//添加字符串对象
list.add(2);
list.add(1);//添加Integ对象
for (Object obj : list) {//遍历集合
String str=(String) obj;//强制转换成String类型
}
}
}
运行结果→
在6—22中,向List集合存入了3个元素,分别是一个字符串和俩个int类型的整数。在取出这些元素时,都将它们强制转换为String类型,由于Integer对象无法转换为String类型,因此程序在运行时会出现报错。
解决方法→
案例学习6—22
import java.util.*;
public class Example23{
public static void main(String[] args) {
ArrayList <Integer> = new ArrayList<Integer>();
list.add(1);//添加字符串对象
list.add(2);
for (Integer str : list) {//遍历集合
System.out.println(str);
}
}
}
运行结果→
1
2
6.6.3 泛型方法
泛型方法的定义与其所在的类是否是泛型类是没有任何关系的,泛型方法所在的类可以是泛型类也可以不是泛型类,定义泛型方法代码如下:
[访问权限]<泛型标识>返回值类型 方法名称(泛型标识 参数名称)
案例学习6—24
public class Example24{
public static void main(String[] args) {
//创建对象
Dog dog=new Dog();
//调用方法,传入的参数是什么类型,返回值就是什么类型
dog.show("hello");
dog.show(12);
dog.show(12.5);
}
}
class Dog{
String eat;
Integer age;
public<T>void show(T t) {
System.out.println(t);
}
}
运行结果→
hello
12
12.5
6.6.4 泛型接口
泛型接口定义完成之后,就要定义此接口的子类,定义泛型接口的子类,有两种方式:一种是直接在子类实现的接口中明确的给出泛型类型;另一种是直接在子类后声明泛型。下面分别对这两种方式进行详细讲解:
1.直接在接口中指定具体类型
当子类明确泛型类的类型参数变量时,外界使用子类的时候,需要传递类型参数变量进来,在实现类中需要定义出类型参数变量。
案例学习6—25
public interface Inter<T>{
public abstract void show(T t);
}
案例学习6—26
public class InterImpl implements Inter<String>{
@Override
public void show (String s) {
System.out.println(s);
}
}
案例学习6—27
public class Example25{
public static void main(String[] args) {
Inter<String> inter = new InterImpl();
inter.show("hello");
}
}
2.在子类的定义上声明泛型类型
当子类不确定泛型类的类型参数变量时,外界使用子类的时候也需要传递类型参数变量进来,在实现类中也需要定义出类型参数变量。
修改6—26,修改后的代码如下:
public class InterImpl<T> implements Inter<T>{
@Override
public void show (T t) {
System.out.println(t);
}
}
在6—27第4~5行代码中间添加如下代码:
Inter<Integer> ii=new InterImpl<>();
ii.show(12);
6.6.5 类型通识符
案例学习6—28
import java.util.*;
public class Example28{
public static void main(String[] args) {
//List集合装载的是Integer
List<Integer> list=new ArrayList<>();
list.add(1);
list.add(2);
test4(list);
}
public static void test(List<?>list) {
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
}
运行结果→
1
2
6.7 JDK8新特性——Lambda表达式
语法格式 | 描述 |
()—>System.out.println("Hello Lambda"); | 无参数,无返回值 |
()—>System.out.println(x) | 有一个参数,并且无返回值 |
x—>System.out.println(x) | 若只有一个参数,小括号可以省略不写 |
Comparator<Integer>com=(x,y)->{System.out.println("函数式接口");return Integer.compare(x,y); } | 有两个以上的参数,有返回值,并且Lambda语句体中有多条语句 |
Comparator<Integer>com=(x,y)->Integer.compare(x,y) | 若Lambda语句体中只有一条语句,return和大括号都可以省略不写 |
(Integer x,Integer y)->Integer.compare(x,y); | Lambda表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出数据类型即“类型推断” |