目录
一、泛型是什么?
Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型,在java的源码和程序中常常看见它的身影。
二、泛型的本质?
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
相当于告诉编译器每个集合接收的对象类型是什么,编译器在编译期就会做类型检查,使得程序更加安全,增强了程序的健壮性
//就是将list集合根据数据类型进行分类,一个list只存储指定类型的元素
ArrayList<String> l1=new ArrayList<String>();
ArrayList<Integer>l2=new ArrayList<Integer>();
三、泛型的好处有哪些?
1.泛型的指定可以使运行时期的问题提前到编译器,避免了数据强转可能出现的问题。
2.避免了装箱和拆箱带来的影响性能问题。
若不指定泛型,默认是object类型。输出时就要进行强转
装箱:任意类型的元素---->object类型
拆箱:object----->需要的元素类型。
3.泛型可以以提高代码的复用性(可以对方法进行抽取,并将类型参数化,由调用者进行传入所需的类型),提高开发效率。
四、泛型的用法
泛型可以使用在类,接口,方法上
参数类型的规范,一般是使用单个大写字母表示
E:Element(元素)
T:Type(类型)
K:Key(键)
V:Value(值)
N:Number(数值类型)
?:通配
1、泛型类
格式:public class 类名 <泛型类型1,...> { }
public class MyGenerics<T> {
private T type;
public T getType() {
return type;
}
public void setType(T type) {
this.type = type;
}
//构造方法,在创建该类对象时就要指定type
public MyGenerics(T type) {
this.type = type;
}
public static void main(String[] args) {
GenericClass<String> g1 = new GenericClass<>("string");
System.out.println(g1.getType());
GenericClass<Integer> g2 = new GenericClass<>(1);
System.out.println(g2.getType());
}
}
运行结果
2、泛型接口
格式:public <泛型类型> 返回类型 方法名(泛型类型 变量名) { }
public interface MyGenericInterface<T> {
// 获取值
T getValue();
// 设置值
void setValue(T value);
}
class MyClass<T> implements MyGenericInterface<T> {
private T value;
// 实现获取值方法
@Override
public T getValue() {
return value;
}
// 实现设置值方法
@Override
public void setValue(T value) {
this.value = value;
}
public static void main(String[] args) {
// 创建一个MyClass对象,并指定泛型类型为String
MyClass<String> myStringClass = new MyClass<>();
// 设置值为字符串
myStringClass.setValue("Hello, generics!");
// 获取值并打印
String stringValue = myStringClass.getValue();
System.out.println("String value: " + stringValue);
// 创建一个MyClass对象,并指定泛型类型为Integer
MyClass<Integer> myIntegerClass = new MyClass<>();
// 设置值为整数
myIntegerClass.setValue(42);
// 获取值并打印
int intValue = myIntegerClass.getValue();
System.out.println("Integer value: " + intValue);
}
}
运行结果
3、泛型方法
通常情况下,当一个方法的形参不确定的情况下,我们会使用到泛型方法。
定义格式:修饰符 <代表泛型的变量> 返回值类型 方法名(参数){ }
public class MyGenericMethod {
// 泛型方法,用于比较两个对象是否相等
public static <T> boolean isEqual(T obj1, T obj2) {
return obj1.equals(obj2);
}
// 泛型方法,用于打印数组中的所有元素
public static <E> void printArray(E[] array) {
for (E element : array) {
System.out.print(element + " ");
}
System.out.println();
}
public static void main(String[] args) {
// 使用isEqual方法比较整数
System.out.println("是否相等:" + isEqual(10, 10));
System.out.println("是否相等:" + isEqual("hello", "world"));
// 使用printArray方法打印整数数组和字符串数组
Integer[] intArray = {1, 2, 3, 4, 5};
String[] stringArray = {"apple", "banana", "orange"};
System.out.print("Integer Array: ");
printArray(intArray);
System.out.print("String Array: ");
printArray(stringArray);
}
}
运行结果
4、自定义泛型
一般在写项目是会使用到自定义泛型,也就是自己封装一个类,类里填写所需要的字段
也就是实体类,将对象存入到集合中
public static void main(String[] args) {
//创建学生1
Student student1 = new Student();
student1.setName("学生1");
student1.setAge(10);
//创建学生2
Student student2 = new Student();
student2.setName("学生2");
student2.setAge(12);
ArrayList<Student> students=new ArrayList<>();
//添加到list
students.add(student1);
students.add(student2);
//输出list
System.out.println(students);
//遍历集合
for (Student student : students) {
System.out.println(student);
}
}
运行结果
五、上限通配符
<? extends 类> 表示?可以指代任何类型,但是该类型必须是后面类的子类。
import java.util.ArrayList;
import java.util.List;
public class WildcardBoundsExample {
public static void main(String[] args) {
List<Integer> integers = new ArrayList<>();
integers.add(1);
integers.add(2);
integers.add(3);
// 以下限定了通配符的类型必须是Number或其子类
printList(integers);
}
private static void printList(List<? extends Number> list) {
for (Number number : list) {
System.out.println(number);
}
}
}
六、下限通配符
<? super 类> 此时?表示可以指代任意类型,但是该类型必须是后面类的父类。
import java.util.ArrayList;
import java.util.List;
public class WildcardBoundsExample {
public static void main(String[] args) {
List<Integer> integers = new ArrayList<>();
integers.add(1);
integers.add(2);
integers.add(3);
// 以上限定了通配符的类型必须是Number或其父类
addToList(integers, 4);
}
private static void addToList(List<? super Integer> list, Integer item) {
list. Add(item);
}
}
在这两个示例中,我们定义了一个方法printList
,它接受一个List<? extends Number>
类型的参数。这意味着我们可以传递任何Number类型或其子类型的List。同样地,我们定义了一个方法addToList
,它接受一个List<? super Integer>
类型的参数。这意味着我们可以传递任何Integer类型或其父类型的List。