引言
JDK1.5之后引入了泛型,泛型刚开始接触时比较难理解,经过慢慢学习,有一些收获,现总结下,既可以加深自身理解,也可以帮助他人。
由于本人水平有限,难免有不对的地方,还请指正。废话不多说,下面正式开始。
为了更直观的说明泛型,现假设一个司机开车的场景。我们需要3个类,Driver(司机)、Ford(福特)、Buick(别克)。
第一版
第一版本代码如下:
public class Buick {
public void run(){
System.out.println("buick run");
}
public void autoRun(){
System.out.println("buick auto-run");
}
}
public class Ford {
public void run(){
System.out.println("ford run");
}
public void fly(){
System.out.println("ford fly");
}
}
public class Driver {
private Object car;
public void drive(Object car){
this.car = car;
if(car instanceof Buick){
System.out.println("I am driving a " + car);
((Buick)car).run();
}else if(car instanceof Ford){
System.out.println("I am driving a " + car);
((Ford)car).run();
}
}
public Object getDrivingCar(){
return car;
}
public static void main(String[] args) {
Driver driver1 = new Driver();
driver1.drive(new Ford());
Driver driver2 = new Driver();
driver2.drive(new Buick());
//...执行其它业务逻辑
/** 获取司机1开的福特车执行fly方法 */
((Ford)driver1.getDrivingCar()).fly();
/** 获取司机2开的别克车执行autoRun方法 */
((Buick)driver2.getDrivingCar()).autoRun();
}
}
简单说明下三个类。Buick类和Ford类都含有run方法,Buick类有autoRun方法,Ford类有fly方法。Driver类有一个drive方法和getDrivingCar方法及内部属性car。main静态方法是演示示例。
通过上面的演示示例可以发现,在调用Driver实例的drive方法时,实际参数向上转型为Object对象,而在调用getDrivingCar方法时,又需要向下转型为具体的car类来调用其特定的方法。那么这种方式会有什么问题呢?
问题是显而易见的,drive方法的参数类型和getDrivingCar的返回值类型是一样的,但由于要支持不同的car,向上转型为Object类型(没有定义为具体的Buick类型或Ford类型),这样外部在调用getDrivingCar时,返回的是一般化的Object,这样就失去了具体类的特征,需要外部强制类型转换。这种显示强制转换方式很容易产生ClassCastException异常(不小心把driver2写成driver1时执行代码时会抛出该异常),并且这种编程错误不能在编译期间发现,而要等到运行期间才能发现,有可能产生隐藏BUG。并且这种方式也不合理,Driver类的使用门槛过高,需要外部代码很小心的处理来防止出现错误,例如在强制转换前用instanceof进行判断。那么有没更好的方式呢?
第二版
第二版本代码如下(只修改Driver类):
public class Driver<T> {
private T car;
public void drive(T car){
this.car = car;
if(car instanceof Buick){
System.out.println("I am driving a " + car);
((Buick)car).run();
}else if(car instanceof Ford){
System.out.println("I am driving a " + car);
((Ford)car).run();
}
}
public T getDrivingCar(){
return car;
}
public static void main(String[] args) {
Driver<Ford> driver1 = new Driver<Ford>();
driver1.drive(new Ford());
Driver<Buick> driver2 = new Driver<Buick>();
driver2.drive(new Buick());
//...执行其它业务逻辑
/** 获取司机1开的福特车执行fly方法 */
driver1.getDrivingCar().fly();
/** 获取司机2开的别克车执行autoRun方法 */
driver2.getDrivingCar().autoRun();
}
}
Driver类声明中使用的<T>,即泛型T。你可以把T类型理解成代表任意一种具体类型的类型。同时修改drive方法参数类型和getDrivingCar方法返回值类型及私有属性car都是T类型。那么这样做有什么好处呢?
从main方法的演示使用代码可以看出,在实例化Driver类时,需要指定具体的T类型(driver1中的Ford和driver2中Buick)。实例化之后,调用getDrivingCar方法的返回类型也是相应的具体类型,从而可以直接调用具体类型特定的方法。
比较第一版的Driver类,改进版的Driver类,只需要使用者在类实例化时指定具体的T类型,在后续操作中不需要进行强制类型转换,从而减少出错的可能性,提高了代码的安全性。
通过泛型T,很轻松对drive方法参数类型、getDrivingCar方法返回值类型及私有属性car类型这三处地方的类型进行了统一,且不失具体性(不像第一版将car申明为Object类型)不需要额外的代码成本,类结构看上去清晰明了。对外部使用者,使用门槛也低,不会出现不小心弄错类型的错误(想出现也不可能,如果指定了错误类型,会在编译期间提示错误)
上面的示例演示了泛型最基本的用法。通过泛型,很容易在类的成员变量或方法参数或方法返回值之间声明为统一类型且不失类型的具体性(在类定义中是泛型,但在实例化时需要指定具体的类型)
联系实际
现在大家应该对泛型有了一个基本的了解。下面举个实例项目中的例子,更进一步说明问题。
项目中一般都需要分页类,简化版如下
/**
* <简单分页类>
*/
public class SimplePage {
/** 每页显示的记录数*/
private int numPerPage;
/** 总记录数 */
private int totalCount;
/** 当前页 */
private int pageNum;
//...省略其它方法
}
/**
* <带内容分页类>
*/
public class Pageable<E> extends SimplePage {
/**
* 本页内容
*/
private List<E> list;
/**
* <设置内容>
* @param list
*/
public void setList(List<E> list) {
this.list = list;
}
/**
* <获取内容>
* @return
*/
public List<E> getList() {
return list;
}
}
SimplePage:简单分页类,包含当前页,每页显示记录数,总记录数等基本成员属性。
Pageable:业务数据分页类,继承自简单分页类,带有本页数据信息。
比如要分页查询用户信息时,假设有User类封装用户信息。使用代码如下:
Pageable<User> pageInfo = new Pageable<User>();
//...分页获取出用户信息,并调用setList方法将用户信息放入pageInfo实例中
/** 其它地方获取到userList,进行其它业务操作 */
List<User> userList = pageInfo.getList();
使用起来非常简单,今天就码到这里了,未完待续。
码字不易,转载请标明出处
版权声明:本文为博主原创文章,未经博主允许不得转载。
分享到:
相关推荐
这些“java泛型学习全面页面下载资料”很可能包含以下内容: 1. **泛型的基本概念**:解释了泛型是什么,以及如何通过使用尖括号`<>`来定义泛型类、泛型接口和泛型方法。 2. **类型参数**:介绍如何定义类型参数,...
Java泛型是Java编程语言中的一个关键特性,它在2004年随着JDK 5.0的发布被引入,极大地增强了代码的类型安全性和重用性。泛型允许我们在编写类...通过深入学习和实践,我们可以更高效地利用泛型来设计和实现复杂系统。
Java泛型是Java编程语言中的一个关键特性,它在2004年随着JDK 5.0的发布被引入,极大地增强了代码的类型安全性和重用性。本篇文章将带你入门Java泛型,通过实例深入理解其核心概念。 1. **泛型的基本概念** - 泛型...
本压缩包包含了一些关于Java泛型的实例,旨在帮助学习者深入理解和应用这一特性。 泛型的主要目标是允许在编译时检查类型安全,并且所有的强制转换都是自动和隐式的,提高了代码的重用率。在Java中,泛型主要体现在...
Java泛型是Java编程语言中的一个关键特性,它在2004年随着JDK 5.0的发布被引入,极大地增强了类型安全性和代码可读性。...对于Java泛型的例子,可以通过运行和分析压缩包中的`generic`文件来加深理解和实践。
通过学习和练习这些内容,你可以深入理解Java集合框架的核心概念和泛型的应用,从而在编程实践中更加灵活和高效地处理数据。同时,不断的学习和实践是提升技能的关键,希望你能在Java世界中不断进步。
【Java 泛型】是Java编程语言中一个强大的...总之,这个压缩包包含的内容涉及了Java泛型、Java Web开发基础、以及现代Web应用中数据存储的几种方式,对于深入理解和实践Java编程,尤其是后端开发有着重要的参考价值。
通过阅读和理解`java泛型实例讲解代码`中的代码,你可以深入学习如何在实际编程中应用这些概念,以及它们如何提升代码的健壮性和可维护性。这个压缩包可能包含了各种示例,如泛型类、泛型方法、边界限制等,通过这些...
学习这部分内容对于Java开发者至关重要,因为理解并熟练掌握Java集合框架和泛型,能有效地提升代码质量和效率,减少运行时错误。此外,了解枚举类型有助于编写更安全、更整洁的代码。通过深入研究和实践,开发者能够...
Java IO流、XML和泛型是Java编程中的关键概念,对于任何Java开发者来说,理解和熟练掌握这些技术至关重要。本文将深入探讨这三个主题,并通过具体的例子进行学习。 首先,我们来看Java IO流。IO流在Java中是用来...
Java编程语言中的反射和泛型是两个非常重要的概念,它们为开发者提供了强大的工具来操作类、接口、对象以及参数类型。在"myreflect.rar"这个压缩包中,我们可以期待找到一系列关于这两个主题的源代码示例,这将有助...
《Java泛型与集合》一书不仅详细介绍了泛型的基本概念和高级特性,还深入探讨了集合框架的使用方法和最佳实践。通过学习本书,读者将能够掌握Java泛型的核心技术,提高代码的质量和可维护性,同时充分利用集合框架的...
在Java编程语言中,泛型是一种强大的工具,它允许我们在编写代码时指定类型参数,从而提高了类型安全性和代码重用性。在Java SE 1.5及更高...学习泛型需要时间和实践,但一旦掌握,将极大地提升代码质量和开发效率。
Java泛型在运行时会被类型擦除,这意味着所有的泛型信息在编译后都会消失,替换为原始类型。因此,泛型主要在编译时提供类型检查,并不改变运行时的行为。 六、泛型与反射 由于类型擦除,泛型在反射中的使用需要...
Java5.0泛型编程是Java开发中的一个重要里程碑,它引入了一种强大的类型系统机制,大大增强了代码的类型安全性,并减少了在编译期间和运行时...通过深入学习和实践,开发者可以编写出更加高效、安全且易于维护的代码。
Java泛型是自Java 5版本引入的一种强大的类型系统特性,它允许我们在编程时指定容器(如列表、集合等)所存储的数据类型。这增强了代码的类型安全性...通过不断学习和实践,我们可以更好地掌握Java泛型这一强大的工具。
Java泛型是Java编程语言中的一个关键特性,它允许在定义类、接口和方法时指定类型参数,从而增强了代码的类型安全性和重用性。在本小测试中,我们将探讨几个与Java泛型相关的概念:通配符(Wildcards)、消除...
在学习Java反射和泛型时,理解它们的概念和使用场景是非常重要的。反射提供了一种动态操控程序的能力,常用于框架开发、插件系统、元数据处理等。而泛型则提高了代码的可读性和安全性,减少了类型转换的工作。结合...
JAVA学习是每位初学者步入编程...以上就是JAVA学习笔记的主要内容,对于非计算机专业的人来说,逐步理解并实践这些知识点将有助于建立起坚实的JAVA编程基础。在学习过程中,不断练习和实际应用是巩固知识的最好方式。
在本月的“Java 理论和实践”中,Brian Goetz 分析了束缚第一次使用泛型的用户的常见陷阱。您可以通过讨论论坛与作者和其他读者分享您对本文的看法。(也可以单击本文顶端或底端的讨论来访问这个论坛。)