网站建设手机源码,wordpress添加用户关闭邮箱,很看好未来做生鲜的网站,网站租用空间价格Java中的泛型#xff08;Generics#xff09;
在Java中#xff0c;泛型是JDK 5引入的一个非常重要的特性#xff0c;它允许你在定义类、接口和方法时使用类型参数#xff08;type parameters#xff09;。使用泛型的主要好处是可以提供编译时的类型检查#xff0c;减少…Java中的泛型Generics
在Java中泛型是JDK 5引入的一个非常重要的特性它允许你在定义类、接口和方法时使用类型参数type parameters。使用泛型的主要好处是可以提供编译时的类型检查减少类型转换的代码并增强代码的可读性和可重用性。
0.通俗理解
想象一下你有一个大箱子类这个箱子可以装很多东西比如苹果、橙子或者玩具车。但是每次你只能装一种东西并且一旦你决定装苹果那么这个箱子就只能装苹果了不能装橙子或玩具车。这样虽然可以但不是很灵活。 现在有了“泛型”这个神奇的工具你可以把这个箱子变成一个“万能箱”。这个“万能箱”在制造的时候并没有决定要装什么而是留了一个“空位”给你来指定。你可以告诉它“我要装苹果”于是它就变成了装苹果的箱子你也可以说“我要装橙子”它就变成了装橙子的箱子。甚至你还可以说“我要装玩具车”它也能满足你的需求。 这个“空位”就是泛型中的“类型参数”你可以把它想象成一个可以插入不同类型的小插片。当你插入“苹果”插片时箱子就变成了苹果箱插入“橙子”插片时就变成了橙子箱。 使用泛型的好处是你可以编写更加通用的代码而不需要为每种类型都写一遍。比如你可以写一个通用的“万能箱”类然后告诉它你要装什么它就能自动适应。这样你的代码就更加灵活、可重用而且减少了出错的可能性。 所以泛型就像是一个魔法箱子让你的代码更加灵活、高效和通用。
1. 泛型类
泛型类就是使用类型参数声明的类。类型参数在类声明中定义然后在整个类体中使用。
public class BoxT {private T t;public void set(T t) { this.t t; }public T get() { return t; }public static void main(String[] args) {BoxInteger integerBox new Box();integerBox.set(new Integer(10));System.out.println(integerBox.get() * 2); // 输出 20BoxString stringBox new Box();stringBox.set(Hello World);System.out.println(stringBox.get().toUpperCase()); // 输出 HELLO WORLD}
}在上面的例子中Box类是一个泛型类它使用了一个类型参数T。然后我们在main方法中创建了两种类型的Box对象BoxInteger和BoxString。
补充 你可以在使用泛型类时不指定泛型参数但是这样做会失去泛型的一些优点如类型安全和避免不必要的类型转换。 例如你可以创建一个没有指定泛型参数的 ArrayListArrayList list new ArrayList(); 这个 list 可以添加任何类型的对象。但是当你从 list 中获取元素时你需要进行类型转换因为 list.get(int index) 方法将返回一个 Object 类型的引用。 如果你在创建 ArrayList 时指定了泛型参数如 ArrayListString那么这个 ArrayList 只能添加 String 类型的对象尝试添加其他类型的对象将导致编译错误。同时list.get(int index) 方法将返回一个 String 类型的引用无需进行类型转换。 因此虽然可以在使用泛型类时不指定泛型参数但是为了获取泛型的优点如类型安全和避免类型转换建议在使用泛型类时指定泛型参数。
2. 泛型接口
和泛型类类似泛型接口也是使用类型参数声明的接口。
public interface ListE {void add(E element);E get(int index);// ... 其他方法
}虽然上面的List接口和Java标准库中的java.util.List接口很相似但这里只是为了示例。
3. 泛型方法
泛型方法是指使用类型参数声明的方法。类型参数在方法签名中定义然后在方法体中使用。
public class GenericMethods {// 泛型方法使用类型参数Tpublic static T void printArray(T[] array) {for (T item : array) {System.out.print(item );}System.out.println();}public static void main(String[] args) {Integer[] intArray {1, 2, 3, 4, 5};printArray(intArray); // 输出整数数组String[] stringArray {Hello, World};printArray(stringArray); // 输出字符串数组}
}在上面的例子中printArray是一个泛型方法它接受一个类型参数T并打印出该类型数组的所有元素。
4. 类型通配符?
在Java中?是一个特殊的类型通配符它表示未知的类型。类型通配符主要用于泛型方法和泛型类的参数定义中。
List? wildcardList new ArrayListString();
// wildcardList.add(new Object()); // 编译错误因为不知道具体类型if (wildcardList instanceof ListString) { // 注意这种instanceof检查是不合法的// ...
}不过类型通配符还提供了两种限制上界extends和下界super。
上界extends表示类型参数必须是某种类型的子类型。
List? extends Number numberList new ArrayListInteger();
// numberList.add(new Double(3.1415)); // 编译错误
Number n numberList.get(0); // 没问题下界super表示类型参数必须是某种类型的超类型或相同类型。
List? super Integer intList new ArrayListNumber();
intList.add(new Integer(10)); // 没问题
// Number n intList.get(0); // 编译错误因为可能是Number的其他子类型5. 泛型擦除Type Erasure
在Java中泛型是通过类型擦除来实现的。这意味着在运行时泛型信息会被擦除所有的泛型类型都会变成原始类型raw type。这就是为什么你不能在运行时检查一个对象是否是某个泛型类型的实例如上面的instanceof检查。但是Java编译器会在编译时检查泛型的使用确保类型安全。
总结
泛型是Java中一个非常强大的特性它允许我们编写更加灵活和可重用的代码。通过使用泛型我们可以减少类型转换的代码。