在java语言中,我们通俗讲一个类是另一个类的子类型,是通过使用extends要害字去继续某一个类或者使用implements要害字去实现某些接口。这样我们在编程时就可以面向接口或基类进行编程,如:
Number num1 = new Integer(1);
Number num2 = new Double(2.1d);
这个就是所谓的替换原则,替换原则的定义是:
Substitution Principle: a variable of a given type may be assigned a value of any subtype of that type, and a method with a parameter of a given type may be invoked with an argument of any subtype of that type.
大概的意思是说某种类型的变量可以被该类型的任何子类所赋值,一个方法中的参数也可以被该参数的任何子类进行调用。
现在我们再来看看泛型中替换原则的适用性:
Example2.1
List listNums = new ArrayList();
nums.add(10);
nums.add(8.88);
在example2.1 中,可以看出替换原则被很好地应用在这里,ArrayList是List的子类,我们提供给listNums变量的类型参数为Number,往 listNums中添加元素时,10被封箱为Integer类型,而Integer是Number的子类,第三行的情况类似。
Example2.2
List intList = new ArrayList();
List numList = intList; //compile error
…
numList.add(1.35); // can‘t do that
根据替换原则,我们会很轻易想到,既然Integer是Number的子类,则我们应该可以将List的变量赋给 List的变量,但从实际情况表明,List并不是List的子类。
我们不妨试想想,若果List类型的变量可以成功赋值给List类型的变量,会出现什么情况?我们可能在程序的某个位置添加一个double类型的元素进去numList中,而实质上在numList中其它元素都是Integer 的类型的元素,这样就违反了泛型的初衷了。
有时,我们确实希望将形如List的List对象赋给List的变量,这时就要使用extends要害字的通配符。
(2) 使用extends要害字的通配符
Example2.3
List intList = new ArrayList();
List<? extends Number> numList = intList();
…
numList.add(1.35); //compile error (can‘t do that)
从Example2.3看到numList这个变量,我们可以将类型参数为Number及其Number子类的List赋给它。
记住一条规则假如你使用了“? extends T”,一般情况下,你不能往该数据结构中put元素,而你可以做的就是get元素。
假如要往内put元素,就需要使用下面提到的super要害字的通配符。
(3) 使用super要害字的通配符
Example2.4
List intList = new ArrayList
List<? super Integer> numList = intList;
numList.add(3); //can put integer or null
在example2.4 我们可以看到<? super Integer>的意思为,我们可以将类型参数为Integer或Integer超类的List赋给 numList变量,并且可以put元素到列表中(注重:在该例子中put进的元素只能为Integer或null类型)。
一条比较通用的规则:假如要往List中put元素则用<? super T>,假如要从List中get元素则用<? extends T>,假如既要get又要put则不使用通配符。
分享到:
相关推荐
4. 泛型方法:使用类型形参定义的方法,例如 `public static void test(List<T> c)`。 泛型的使用: 1. 定义泛型类:`public class Applet<T>{public T info; ...}` 2. 使用泛型类:`Applet<String> applet = new ...
下面将详细解释Java泛型的基本概念、使用方式以及相关的知识点。 1. 泛型的基本概念: - 泛型是一种参数化类型,允许在定义类、接口和方法时使用类型参数,从而创建一种可以适用于多种类型的通用代码。 - 泛型的...
Java泛型是Java编程语言中一个强大的特性,它允许在定义类、接口和方法时使用类型参数,从而实现参数化类型。泛型的主要目标是提高代码的类型安全性和重用性,减少类型转换的麻烦,并在编译时捕获可能的类型错误。...
- 上界通配符:`List<? extends Fruit>` 表示该列表可以包含`Fruit`及其子类的元素。 - 下界通配符:`List<? super Apple>` 表示该列表可以包含`Apple`及其父类的元素。 通过使用通配符,我们可以编写更加灵活且...
11. **泛型与反射**:在使用反射操作泛型类型时,需要注意类型信息在运行时是不可见的,需要通过其他方式(如注解或硬编码)来获取。 以上就是Java 5泛型新特性的一些关键点。通过这些特性,我们可以编写更安全、更...
这样,可以根据枚举值来确定应该使用的泛型类型。 6. **集合的泛型操作**: 在Java中,集合框架的泛型操作包括添加、删除、查找和遍历元素。这些操作在运行时会进行类型检查,确保插入的元素与集合的泛型类型匹配...
1. 泛型集合:使用泛型可以指定集合元素的类型,如`List<String>`只能存储String对象,防止了添加其他类型元素的错误。 2. 类型安全的迭代器:通过泛型,我们可以直接遍历集合而无需进行强制类型转换,降低了出错的...
在Java编程语言中,集合框架是处理对象数组的重要工具,而泛型的引入极大地提高了代码的类型安全性和可读性。...在实际编程中,应根据需求灵活选择合适的泛型使用方式,以充分利用Java泛型的优势。
Java泛型是Java编程语言中的一个关键特性,它允许开发者在编写代码时引入类型参数,以提高代码的灵活性、安全性和可复用性。泛型的主要目标是在编译时进行类型检查,确保代码在运行时不会出现类型转换异常。下面我们...
1. 非泛型时代:在Java泛型出现之前,程序员需要通过类型转换来确保对象的正确使用,这容易导致运行时错误,如`ClassCastException`。 2. 早期的泛型尝试:JDK 1.2引入了集合框架,但并未实现泛型。尽管提供了如...
3. **边界**:泛型类型参数可以有边界,比如`<T extends Number>`,表示`T`必须是Number或其子类。这限制了可以使用的类型范围,增强了安全性。 4. **通配符**:如`?`,用于表示任意类型,但有一些限制。例如,`...
4. **基本类型参数**: Java泛型不能直接接受基本类型(如int、char),但可以通过创建对应的包装类(如Integer、Character)来使用。 5. **协变与逆变**: 在泛型中,类型参数的使用会影响类型安全。比如,List是...
Java 泛型是 Java 5 中引入的一种编程技术,旨在提高代码的复用性和类型安全性。泛型允许开发者编写出“非特定类型”的代码,能够根据实际情况选择合适的类型,从而提高代码的灵活性和可维护性。 1. 泛型定义和使用...
2. **类型擦除**: 泛型在编译后会进行类型擦除,因此在运行时无法直接获取泛型类型信息。但泛型可以提供编译时的类型检查。 3. **通配符**: 通配符用于表示对类型的一般限制,如`?`表示任何类型,`? extends Number...
Java泛型在运行时会被类型擦除,这意味着所有的泛型信息在编译后都会消失,替换为原始类型。因此,泛型主要在编译时提供类型检查,并不改变运行时的行为。 六、泛型与反射 由于类型擦除,泛型在反射中的使用需要...
"JAVA泛型笔记.pdf" Java 泛型(Generic)是 Java 5 中引入的一种机制,它允许开发者在编写类、接口和方法时指定类型参数,以提高代码的灵活性和可重用性。泛型的主要特点是可以在编译期检查类型的正确性,避免了...
本文将深入探讨Java泛型类型擦除的概念,并介绍在类型擦除后,为了保持泛型的安全性和便利性,Java设计者所采取的一些补偿机制。 1. **类型擦除**: - 在编译期间,所有的泛型类型信息都会被替换为它们的实际类型...