1、概念:
广泛的类型。定义时不确定类型,在使用时来确定,该类型就是泛型。
2、使用泛型语法:
<泛型类型1,泛型类型2,…泛型类型n>
泛型类型:必须是引用类型,如果需要基本数据类型作为泛型,请使用包装类。
3、代码示例
import java.util.ArrayList;
import java.util.List;
public class Demo6_泛型 {
public static void main(String[] args) {
/*List list = new ArrayList();
list.add("bbb");
list.add("abc");
list.add(123);
for (int i = 0; i < list.size(); i++) {
Object o = list.get(i);
String s = (String) o;//需要向下类型转换//java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
String substring = s.substring(1);
System.out.println(substring);//bb bc
}*/
//问题:
//1、如果使用元素中的特有方法,必须向下类型转换。
//2、由于需要向下类型转换,容易类型转换异常问题。
//解决:使用泛型
//1、类型检查,符合该类型的元素才能添加到集合中。
//2、由于类型检查,所以元素类型必然确定,所以无需类型转换。
List<String> list2 = new ArrayList<String>();
list2.add("bbb");
list2.add("abc");
//list2.add(123);报错,类型检查
for (int i = 0; i < list2.size(); i++) {
String s = list2.get(i);
System.out.println(s.substring(1));
}
}
}
4、泛型类
(1)语法
访问修饰符 class 类名<泛型字母1,泛型字母2,…>{
泛型类型的成员/其他类型的成员
}
泛型字母1,泛型字母2,…:一般都是大写字母,表示该类定义时,泛型类型无法确定。类创建对象时决定。
泛型类型的成员:泛型类型可以作为属性类型,方法的返回值类型,参数类型来使用。
(2)代码示例
import java.util.ArrayList;
import java.util.List;
//泛型类
class Source<T>{
private T data;
private int a;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
public class Demo6_泛型 {
public static void main(String[] args) {
//泛型类的泛型,在对象创建中才能确定,当泛型类型被确定,其泛型类中使用到泛型类型都确定了。
Source<String> s = new Source<String>();
//确定泛型类型技术:
//菱形技术
Source<String> s2 = new Source<>();
//擦除技术
Source<String> s3 = new Source();
s3.setData("巧克力");
String data = s3.getData();
System.out.println(data);
//注意:使用泛型类时,不去确定泛型的类型,泛型类的泛型的类型是Object类型。
Source s4 = new Source();
s4.setData(new Object());
}
}
(3)泛型类在API中体现
5、泛型方法
(1)语法
访问修饰符 <泛型字母1,泛型字母2,…>返回值类型 方法名(参数列表){
方法体
}
泛型字母1,泛型字母2,…:一般都是大写字母,该泛型类型由参数类型决定。
(2)代码示例
import java.util.ArrayList;
import java.util.List;
//泛型类
class Source<T> {
private T data;
private int a;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
//泛型方法
//泛型方法提出原因:该方法不希望使用泛型类的泛型。
//注意1:非静态泛型方法的方法体和参数列表中可以使用泛型类的泛型
// 2:静态泛型方法的方法体和参数列表中不可以使用泛型类的泛型。
public static <Q> Q method(Q q/*, T tb 报错*/) {
//this.data = t; 报错
return q;
}
}
public class Demo6_泛型 {
public static void main(String[] args) {
Source<String> s = new Source<>();
Integer method = s.method(10);
System.out.println(method);//10
}
}
(3)泛型方法在API中体现
6、泛型接口
(1)语法
访问修饰符 interface 接口名<泛型字母1,泛型字母2,…>{
泛型类型成员(方法)
}
(2)代码示例
interface Inter<E>{
//接口泛型类型不能使用接口属性中,接口属性都是静态的。
public E method();
}
//通过实现将泛型接口中泛型传递给实现类
class Impl<E> implements Inter<E>{
@Override
public E method() {
return null;
}
}
//通过继承将泛型接口中泛型传递给子接口
interface subInter<E> extends Inter<E>{
public void function(E e);
}
public class Demo6_泛型 {
public static void main(String[] args) {
//泛型接口的作用:传递泛型
Impl<String> impl = new Impl<>();
String method = impl.method();
}
}
(3)泛型接口在API中体现
7、泛型通配符
(1)语法
(2)代码示例
public class Demo6_泛型 {
public static void foreach(List<?> list) {
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
public static void main(String[] args) {
//泛型通配符
//需求:对老师集合,学生集合,人类集合进行遍历并输出每个元素数据。
List<Teacher> tlist = new ArrayList<>();
Teacher t1 = new Teacher("孔子", 1000L);
Teacher t2 = new Teacher("孟子", 2000L);
Teacher t3 = new Teacher("老子", 3000L);
tlist.add(t1);
tlist.add(t2);
tlist.add(t3);
List<Puple> plist = new ArrayList<>();
Puple p1 = new Puple("小明", 6);
Puple p2 = new Puple("小红", 7);
Puple p3 = new Puple("小杰", 8);
plist.add(p1);
plist.add(p2);
plist.add(p3);
List<Person> perlist = new ArrayList<>();
Person per1 = new Person("路人甲");
Person per2 = new Person("路人乙");
Person per3 = new Person("路人丙");
perlist.add(per1);
perlist.add(per2);
perlist.add(per3);
foreach(tlist);
foreach(plist);
foreach(perlist);
}
}
8、泛型上下限
(1)概念:用于控制泛型通配符可以接口的泛型类型范围。
(2)语法: