Java 5.0引入泛型以后,提高了类型安全性,然而也给编程带来了新的挑战以及新的误区,类型转换就是一个很好的例子。引入泛型以后,对象的类型似乎由两个类型构成:集合类型和参数类型,例如List<Integer> list = new LinkedList<Integer>(),似乎list的类型由List和Integer共同决定。如果真是这样,那么我们如果希望对list进行类型转换,我们该怎么办?是对List转换,还是对Integer转换?要解答上面的问题很简单,编写如下的代码,运行之就可看出端倪:
public static void wrongConversion() {
List < Integer > list = new LinkedList < Integer > ();
list.add( 1 );
list.add( 2 );
list.add( 3 );
// 下面的代码无法编译通过。
// List<Number> wrongList = list;
}
public static void rightConversion() {
LinkedList < Integer > list = new LinkedList < Integer > ();
list.add( 10 );
list.add( 20 );
list.add( 30 );
List < Integer > rightList = list;
for ( int number: rightList) {
System.out.println(number);
}
}
如果你运行上面的代码,你会发现前一个函数根本无法通过编译,而后一个函数不仅编译成功,而且能得到正确结果。这似乎给出了一个结论:对象的类型由集合类型来决定,对对象进行类型转换时也是对集合类型进行转换。事实确实如此!那么为什么会如此呢?
我们可以回忆一下以前我们对参数类型的描述:参数类型不过是一个占位符而已,在编译时,它会被具体的类型代替,同时对添加到集合对象中的数据进行参数检查;如果添加到对象中的数据类型不是指定的具体类型或其子类型,则编译出错;而且,编译以后,该占位符会被移除,运行时你是无法得到任何集合类型中数据的类型信息的。简而言之:
List<String> strings = new LinkedList<String>( );
List<Integer> ints = new LinkedList<Integer>( );
上面的代码在运行时和
List strings = new LinkedList( );
List ints = new LinkedList( );
毫无二致。了解了这一点以后,相信我们对于类型转换也会有更深的理解了。
泛型给我们带来了好处,使我们在编译时就能发现很多错误;然而任何事物都是柄双刃剑,泛型也不例外。泛型的缺点最明显之处就在于类型转换。如果你读过前面的文章,肯定看到过不带参数类型的集合对象转换为带参数类型的集合对象,其实不仅仅如此,这两者之间可以任意转换。这就意味着一点,我们不仅可以对集合类型进行转换,也可以对参数类型进行任意的转换。这似乎与前面的描述不符,因为上面的代码中的List<Number> wrongList = list;根本无法编译通过。确实如此,这行代码确实无法编译通过,不过我们中间做一步处理以后,上面的转换就可以正常编译了:
List mediaList = list;
List<Number> wrongList = mediaList;
由此可见,泛型在给我们带来好处的同时,也带来了无数陷阱,我们在编程时需十分注意,而Java的泛型机制也需要不断更新。
最后和以往一样,以一个拙劣的程序结束本文:
上面程序的输出结果为: rightConversion
10
20
30
badConversion
1
2
3
java.lang.ClassCastException: java.lang.String
at com.jiang.tiger.chap1.GenericReflection.fillList(GenericReflection.java:11)
at com.jiang.tiger.chap1.GenericReflection.badConversion(GenericReflection.java:32)
at com.jiang.tiger.chap1.GenericReflection.main(GenericReflection.java:109)
badConversion2
1
2
java.lang.ClassCastException: java.lang.String
at com.jiang.tiger.chap1.GenericReflection.badConversion2(GenericReflection.java:45)
at com.jiang.tiger.chap1.GenericReflection.main(GenericReflection.java:116)
wrongConversion
100
200
300
java.lang.ClassCastException: java.lang.Double
at com.jiang.tiger.chap1.GenericReflection.wrongConversion(GenericReflection.java:62)
at com.jiang.tiger.chap1.GenericReflection.main(GenericReflection.java:123)
badReflection
Filling list and printing in normal way
1
2
3
1
2
3
4
5
6
java.lang.ClassCastException: java.lang.String
at com.jiang.tiger.chap1.GenericReflection.printList(GenericReflection.java:17)
at com.jiang.tiger.chap1.GenericReflection.badReflection(GenericReflection.java:99)Printing with illegal values in list
1
2
3
1
2
3
4
5
6
at com.jiang.tiger.chap1.GenericReflection.main(GenericReflection.java:130)
分享到:
相关推荐
3. **类型转换与赋值转换**: 在"泛型类型转换Demo"中,可能涉及到不同泛型类型的赋值转换。例如,如果我们有一个`List<Number>`,我们可以通过类型转换将其赋值给`List<Integer>`,因为Integer是Number的子类。...
与显式强制类型转换不同,`as`关键字不会抛出异常,而是返回`null`,因此需要检查转换后的结果是否为`null`。 #### 总结 本文介绍了C#2.0中的两个重要概念:泛型和强制类型转换。通过泛型,可以编写类型安全且高度...
5. **泛型与类型转换** 泛型方法的一个优点是避免了显式类型转换。由于类型安全,当你从泛型方法返回对象时,不需要进行类型转换,这减少了潜在的运行时错误。 6. **泛型方法与非泛型方法的比较** - **性能**:...
JDK 5.0 中增加的泛型类型,是 Java 语言中类型安全的一次重要改进。但是,对于初次使用泛型类型的用户来说,泛型的某些方面看起来可能不容易明白,甚至非常奇怪。在本月的“Java 理论和实践”中,Brian Goetz 分析...
在提供的文档内容中,示例代码展示了不使用泛型时在集合中添加和取出元素需要进行类型转换。例如,从`ArrayList`中取出对象时需要强制转换为`String`类型。如果原对象不是`String`类型,则会抛出异常。而使用泛型后...
标题提到的“泛型工具类”主要指的是一种设计模式或编程实践,它提供了一系列用于处理泛型类型的工具方法。这类工具类通常用于辅助其他类或框架(如DAO层)更高效地操作泛型数据。具体到给定的`GenericUtil`类,其...
- 在类型擦除后,可以使用 `instanceof` 和强制类型转换来检查对象的实际类型,以确保类型安全。 - 但是,这种做法应该谨慎使用,因为它破坏了泛型的抽象性。 8. **反射与泛型**: - 反射API在泛型类型擦除后...
然而,Java 的泛型在运行时是被擦除的,这意味着在运行时刻,所有的泛型类型信息都会丢失,无法直接用来创建对象或进行类型检查。这导致我们无法使用 `new T()` 或 `instanceof` 这样的操作。为了解决这个问题,我们...
4. **泛型与数据类型转换** - 泛型的主要优点之一是消除显式类型转换的需求。在泛型之前,我们需要手动进行类型转换,如 `Hashtable` 的使用。引入泛型后,如 `List<String>` 直接存储和获取 `String` 对象,无需...
泛型是一种允许编译时类型检查的语言特性,它使得程序员能够编写类型安全的通用类和方法,而无需进行显式的数据类型转换。在Java中,泛型的引入解决了“类型擦除”问题,即在运行时所有泛型类型都被替换为它们的原始...
Java泛型是一种参数化类型机制,允许在编译时提供类型检查和消除类型转换。它主要用于集合框架中,以确保在编译期间元素类型的一致性。泛型类或接口中的类型参数,通常以字母如T(Type)表示。 泛型类的定义语法是...
本文将深入探讨如何在.NET框架下,利用泛型集合与XML元素之间进行数据的转换,以便于数据的持久化存储和加载。我们将讨论泛型集合的概念、XML的基本知识以及它们之间的转换方法。 首先,让我们理解什么是泛型集合。...
1. 泛型与类型转换:在Java中,泛型是用于提供类型安全的工具,允许程序员在代码中指定容器(如List)所存储的数据类型。在问题A中,涉及到将原始类型(如int)转换为泛型(如List)。由于Java的泛型不支持原始类型...
- **装箱**:将值类型转换为引用类型的过程,通常发生在向非泛型集合中添加值类型对象时。 - **拆箱**:将引用类型转换回值类型的过程,通常发生在从非泛型集合中获取值类型对象时。 2. **类型安全问题**:非泛型...
非常方便的datatable类型与List泛型实体对象集合的互相转换,在面向对象的开发中,经常会用到的,如使用上不懂可以咨询我
C# 泛型中的数据类型判定与转换 在 C# 中,泛型是非常...我们可以使用 object 类型作为桥梁,进行具体的类型判定与转换,也可以使用 dynamic 类型来解决类型转换的问题。这些技术可以使得我们的代码更加灵活和通用。
在实际开发中,理解和熟练运用Java集合框架和泛型能够大大提高代码的可维护性和安全性,减少类型转换的麻烦,并使得代码更易于理解和复用。通过以上讲解,相信你已经对这两个主题有了更深入的理解。通过练习和应用,...
- 类型安全:编译器可以在编译时检查类型一致性,避免了类型转换的错误。 - 性能提升:由于类型信息是在编译时确定的,可以避免运行时的装箱和拆箱操作,提高运行效率。 - 代码重用:泛型可以创建可复用的组件,...
1. **装箱与拆箱**:如果泛型结构体需要与引用类型进行交互,可能会涉及装箱(将值类型转换为对象)和拆箱(将对象转换回值类型),这会带来额外的性能成本。 2. **结构体的复制行为**:由于结构体是值类型,当泛型...