一、泛型的定义
泛型的本质是参数化类型,也就是所操作的数据类型被指定为一个参数。
泛型泛指一切类型,能够代表一切类型,是一种在编程中广泛使用的概念,特别是在面向对象编程中。它允许在编写代码时使用类型参数,这些参数在代码被实际使用时才会被具体的类型所替换。简单来说,泛型就是将类型参数化,使得一个类或方法能够操作多种数据类型,而不仅仅是预先定义好的一种或几种类型。
二、如何使用泛型
通过实现一个栈了解什么是泛型和调用泛型的原因。
创建一个int数组,定义一个游标i,定义数组大小,编写添加数据和输出数据的方法。但此时只能存储int类型数据,如果向存储其他类型数据,可以重现创建一个类修改数据类型,但太过繁琐,所以引入泛型,泛指一切类型,能够代表一切类型,将其他数据类型进行转换。这就是使用泛型的好处。
二、如何使用泛型
1.泛型类
泛型类就是在类定义时通过类型参数指定类中某些属性的类型。
①在类后边加< 具体类型名>
②在变量名前加 泛型类型名
class 类名称 <泛型标识、泛型标识,...> {private 泛型标识 变量名;......
}
// 定义一个泛型类Box
public class Box<T> { // T stands for "Type" - 在这里T是一个占位符,用于表示实际的类型 // T类型的变量 private T t; // 添加一个构造方法,接收T类型的参数 public Box(T t) { this.t = t; } // 获取t的值 public T get() { return t; } // 设置t的值 public void set(T t) { this.t = t; } // 示例方法,用于展示泛型类型的信息 public void printTypeInfo() { System.out.println("The type of t is: " + t.getClass().getName()); } // 主方法,用于测试Box类 public static void main(String[] args) { // 创建一个存储整数的Box Box<Integer> integerBox = new Box<>(123); System.out.println(integerBox.get()); integerBox.printTypeInfo(); // 创建一个存储字符串的Box Box<String> stringBox = new Box<>("Hello, World!"); System.out.println(stringBox.get()); stringBox.printTypeInfo(); }
}
2.泛型方法
泛型方法是在调用方法时指定类型参数的方法。
①类名<具体的数据类型> 对象名 = new 类名<具体的数据类型>();
java 1.7以后,后边的<>中具体的数据类型可以省略不写
②类名<具体的数据类型> 对象名 = new 类名<>();
// 定义一个泛型类Box
public class Box<T> { // T stands for "Type" - 在这里T是一个占位符,用于表示实际的类型 // T类型的变量 private T t; // 添加一个构造方法,接收T类型的参数 public Box(T t) { this.t = t; } // 获取t的值 public T get() { return t; } // 设置t的值 public void set(T t) { this.t = t; } // 示例方法,用于展示泛型类型的信息 public void printTypeInfo() { System.out.println("The type of t is: " + t.getClass().getName()); } // 主方法,用于测试Box类 public static void main(String[] args) { // 创建一个存储整数的Box Box<Integer> integerBox = new Box<>(123); System.out.println(integerBox.get()); integerBox.printTypeInfo(); // 创建一个存储字符串的Box Box<String> stringBox = new Box<>("Hello, World!"); System.out.println(stringBox.get()); stringBox.printTypeInfo(); }
}
3.泛型接口
与泛型类类似,泛型接口也是在接口定义时指定类型参数的接口。
public interface Pair<K, V> { public K getKey(); public V getValue();
} // 实现
class OrderedPair<K, V> implements Pair<K, V> { private K key; private V value; public OrderedPair(K key, V value) { this.key = key; this.value = value; } @Override public K getKey() { return key; } @Override public V getValue() { return value; }
}
4.泛型通配符
泛型通配符(Wildcard Types)主要用于不确定或不关心实际类型参数的情况。主要有两种形式:?
和 ? extends Type
、? super Type
。
?
:表示未知的类型。? extends Type
:表示未知的类型,但它是Type或Type的子类型。? super Type
:表示未知的类型,但它是Type的超类型(父类型或自身)。
5.泛型擦除
Java的泛型是通过类型擦除来实现的,这意味着泛型信息在编译时会被擦除,并在运行时被替换为类型参数的上界(通常是Object
)。因此,泛型在运行时是不包含类型信息的,这也是为什么你不能在运行时检查一个泛型对象的实际类型参数的原因。然而,这并不意味着泛型没有类型安全,因为类型检查是在编译时进行的。
6.泛型的好处
- 类型安全:泛型允许在编译时检查类型错误,从而避免了运行时错误。
- 消除类型转换:使用泛型后,很多时候可以自动处理类型转换,减少了代码中的显式类型转换。
- 提高代码复用性:通过泛型,可以编写更加通用的代码,这些代码可以适用于多种数据类型。
- 提高代码清晰度:泛型使得代码更加清晰易懂,因为它明确了数据类型。