反射(reflection)是指在程序运行期间发现更多的类及其属性的能力。
5.1 类、超类和子类
关键字extends表明正在构造的新类派生于一个已存在的类。已存在的类被称为超类(superclass)、基类(base class)或父类(parent class);新类被称为子类(subclass)、派生类(derived class)或孩子类(child class)。
注意:前缀“超”和“子”来源于计算机科学和数学理论中的集合语言的术语。
注意:有些人认为super与this引用时类似的概念,实际上,这种类比并不恰当。这是因为super不是一个对象的引用,不能将super赋给另一个对象变量,它只是一个指示编译器调用超类方法的特有关键字。
注意:super关键字也有两个用途:一是调用超类的方法,二是调用超类的构造器。
一个对象变量可以引用多种实际类型的现象被称为多态(polymorphism)。在运行时能够自动地选择调用的适当方法的现象称为动态绑定(dynamic binding)。
5.1.1 继承层次
由一个公共超类派生处理的所有累的集合被称为继承层次(inheritance hierarchy)。在继承层次中,从摸个特定的类到其祖先的路径被称为该类的继承链。
5.1.2 多态
“is-a”规则的另一种表述法是置换法则。它表明程序中出现超类对象的任何地方都可以用子类对象置换。
警告:在Java中,子类数组的引用可以转换成超类数组的引用,而不需要采用强制类型转换。
5.1.3 动态绑定
弄清调用对象方法的执行过程十分重要。下面是调用过程的详细描述:
1)编译器查看对象的声明类型和方法名。
2)编译器将查看调用方法时提供的参数类型,如果在所有名为f的方法中存在一个其参数类型与提供的参数完全匹配,那么就调用这个方法,这个过程被称为重载解析(overloading resolution)
3)如果方法是private、static、final或者构造器,那边编译器将可以准确地知道应该调用哪个方法,这种调用方式称为静态绑定(static binding)。
4)当程序运行,并且采用动态绑定调用方法时,虚拟机一定调用与x所引用对象的实际类型最合适的那个类的方法。
虚拟机预先为名各类创建了一个方法表,其中列出了所有方法的签名和实际调用的方法。
动态绑定有一个非常重要的特性:无需对现存的代码进行修改,就可以对程序进行扩展。
警告:在覆盖一个方法的时候,子类方法不能低于超类方法的可见性。特别是,如果超类方法是public,那么子类方法一定要声明为public。
5.1.4 阻止继承:final类和final方法
不允许扩展的类被称为final类。
注意:如果将一个类声明为final,只有其中的方法自动地成为final,而不包括域。
5.1.5 强制类型转换
综上所述:
1、只能在继承层次内进行类型转换
2、在将超类转换成子类之前,应该使用instanceof进行检查。
5.1.6 抽象类
为了提高程序的清晰度,包含一个或多个抽象方法的类本市必须被声明为抽象的。
抽象方法充当着占位的角色,它们的具体实现在子类中。扩展抽象类可以有两种选择。一种是在子类中定义部分抽象方法或抽象方法也不定义,这样就必须将子类也标记为抽象类;另一种是定义全部的抽象方法,这样一来,子类就不是抽象的了。
需要注意,可以定义一个抽象类的对象变量,但是它只能引用非抽象子类的对象。
5.1.7 受保护的访问
Java用于控制可见性的4个访问修饰符:
1)仅对本类可见——private
2)对所有类都可见——public
3)对本包和所有子类都可见——protected
4)对本包可见——默认,所谓默认是指没有标明任何修饰符的情况,这是一种不太受欢迎的形式
5.2 Object:所有类的超类
如果没有明确地指出超类,Object就被认为是这个类的最终超类。
在Java中,只有基本类型(primitive type,如数值、字符和boolean)的值不是对象。而所有的数组类型,不管是对象数组还是基本类型的数组都扩展于Object类的类型。
5.2.1 equals方法
Object类中的equals方法用于检测一个对象是否等于另外一个对象。在Object类中,这个方法将判断两个对象是否具有相同的引用。
5.2.2 相等测试与继承
Java语言规范要求equals方法具有下面的特性:
1)自反性:对于任何非空引用x,x.equals(x)应该返回true。
2)对称性:对于任何引用x和y,如果x.equals(y)返回true,那么y.equals(x)也该返回true。
3)传递性:对于任何引用x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)也应该返回true。
4)一致性:如果x和y引用的对象没有发生变化,那么反复调用x.equals(y)应该返回同样的结果。
5)对于任意非空引用x,x.equals(null)应该返回false。
5.2.3 hashCode方法
散列码(hash code)是由对象导出的一个整型值。散列码是没有规律的。
由于hashCode方法定义在Object类中,因此每个对象都有一个默认的散列码,其值为对象的存储地址。
如果重新定义equals方法,就必须重新定义hashCode方法,以便用户可以将对象插入到散列表中。equals与hashCode的定义必须一致:如果x.equals(y)返回true,那么x.hashCode()就必须与y.hashCode()具有相同的值。
5.2.4 toString方法
提示:在调用x.toString()的地方可以用""+x替代。这条语句将一个空串与x的字符串表示相连接。这里的x就是x.toString()。与toString不同的是,如果x是基本类型,这条语句照样能执行。
5.3 泛型数组列表 2010-09-07 169页
一旦能够确认数组列表的大小不再发生变化,就可以调用trimToSize方法。这个方法将存储区域的大小调整为当前元素数量所需要的存储空间数目。垃圾回收器将回收多余的存储空间。一旦整理了数组列表的大小,添加新元素就需要花时间再次移动存储块,所以在确认不会添加任何元素时,再调用trimToSize。
5.3.1 访问数组列表元素
使用add方法为ArrayList添加新元素,而不要使用set方法,它只能替换数组中已经存在的元素内容。
5.3.2 类型化与原始数组列表的兼容性
5.4 对象包装器与自动打包
对象包装器:Integer、Long、Float、Double、Short、Byte、Character、Void和Boolean。(前6个类派生于公共的超类Number。)对象包装器是不可变的,即一旦构造了包装器,就不允许更改包装在其中的值。同时,对象包装器类还是final的,因此不能定义它们的子类。
注意:自动打包规范要求boolean、byte、char≤127,介于-128~127之间的short和int被包装到固定的对象中。
注意:如果想编写一个修改数值参数值的方法,就需要使用在org.omg.CORBA包中定义的持有者(holder)类型,包括IntHolder、BooleanHolder等等。每个持有者类型都包含一个公有(!)域value,通过它可以访问存储在其中的值。
参数数量可变的方法
在JDK5.0以前的版本中,每个Java方法都有固定数量的参数。然而,现在的版本提供了可以用可变的参数数量调用的方法。
5.5 反射
反射库(reflection library)提供了一个非常丰富且精心设计的工具集,以便编写能够动态操作Java代码的程序。
能够分析类能力的程序被称为反射(reflective)。反射机制的功能及其强大:
1、在运行时分析累的能力
2、在运行时查看对象
3、实现数组的操作代码
4、利用Method对象,这个对象很像C++这类语言中的函数指针
5.5.1 Class类
在程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识。这个信息保存着每个对象所属的类足迹。虚拟机利用运行时信息选择相应的方法执行。
5.5.2 使用反射分析类的能力
在java.lang.reflect包中有三个类:Field、Method、Constructor分别拥有描述类的域、方法和构造器。这三个类有一个叫做getModifiers的方法,它将返回一个整数值,用不同的位开关设置描述public和static这些修饰符的使用状况。
Class类中的getFields、getMethod和getConstructors方法将分别返回类支持的public域、方法和构造器数组,其中包括超类的共有成员。Class类的getDeclareFields、getDeclareMethods和getDeclaredConstructors方法将分别返回类中声明的全部域、方法和构造器组成的数组。其中包括私有和受保护成员,但不包括超类的成员。
5.5.3 在运行时使用反射分析对象
除非拥有访问权限,否则Java安全机制只允许查看任意对象有哪些域,而不允许读取他们的值。反射机制的默认行为受限于Java的访问控制。然而,如果一个Java程序没有受到安全管理器的控制,就可以覆盖访问控制。为了达到这个目的,需要调用Field、Method或Constructor对象的setAccessible方法。
setAccessible方法是AccessibleObject类中的一个方法,他是Field、Method和Constructor类的公用超类。这个特性是为调试、持久存储和相似机制提供的。
5.5.4 使用反射编写通用的数组代码
java.lang.reflect包中的Array类允许动态地创建数组。
5.5.5 方法指针
建议仅在必要的时候,才使用Method对象,而最好使用接口和内部类。特别要重申:建议Java开发者不要使用Method对象的回调功能。使用接口进行回调会使得代码的执行速度更快,更易于维护。
5.6 枚举类
在比较两个枚举类型的值时,永远不需要调用equals,而直接使用“= =”就可以了。
enum Size
{
SMALL("S"),MEDIUM("M"),LARGE("L"),EXTRA_LARGE("XL");
private Size(String abbreviation){this.abbreviation=abbreviation;}
public String getAbbreviation(){return abbreviation;}
private String abbreviation;
}
5.7 继承设计技巧
1)将公共操作和域放置在超类
2)不要使用受保护的域。
protected机制并不能够带来更好的保护,起源于主要有两点。第一,子类集合是无限制的,任何一个人都能够由某个类派生一个子类,并编写代码以直接访问protected的实例域,从而破坏了封装性。第二,在Java程序设计语言中,在同一个包中的所有类都可以访问protected域,而不管它是否为这个类的子类。
3)使用继承实现“is-a”关系
4)除非所有继承的方法都有意义,否则不要使用继承。
5)在覆盖方法的时候,不要改变预期的行为。
6)使用多态,而非类型信息。
使用多态方法或接口编写的代码比使用对多种类型进行检测的代码更加易于维护和扩展。
7)不要过多地使用反射
分享到:
相关推荐
第五章 继承与多态.ppt
【继承与多态】是面向对象编程中的两个核心概念,主要在Java等面向对象语言中广泛应用。本章将深入探讨这两个主题。 **继承**是面向对象编程中的一个重要特性,它允许一个类(子类)继承另一个类(父类)的属性和...
继承与派生
Java 类的继承、包及接口是Java编程中的核心概念,它们是构建复杂应用程序的基础。类的继承允许我们创建一个新的类,这个新类基于已存在的类(称为父类或超类),并可以添加新的特性和方法,或者修改父类的行为。这...
本资源包含了"Python程序设计"课程第五章的编程题答案,旨在帮助学生理解和掌握Python编程的核心概念与技巧。 在Python编程中,第五章通常会涵盖一些关键主题,例如函数的使用、模块导入、异常处理、文件操作以及...
例如,在编程课程中,第五章可能涉及面向对象编程(OOP)的概念,如类、对象、继承、多态和封装。如果是数据结构与算法,这个阶段可能会讲解树、图或高级排序算法。如果是网络课程,可能会讲解TCP/IP协议栈、HTTP...
在本习题中,我们将探讨从第一章到第五章涉及到的关键知识点。 第一章通常会介绍Java语言的基础概念,包括: 1. **Java的历史与特性**:Java由Sun Microsystems开发,具有跨平台性、面向对象、安全性、健壮性等...
第五章[1].包、继承、抽象类以及接口
2. **面向对象编程**:Java是一种纯面向对象的语言,第五章可能深入讲解类与对象的概念,包括类的定义、对象的创建与销毁,以及封装、继承和多态这三个面向对象的特性。理解如何通过类和对象来组织代码,是掌握Java...
**Java程序设计基础篇(第8版)第五章编程题答案** 在学习Java编程时,实践是提升技能的关键。本书的第五章可能涵盖了基础至进阶的编程概念,旨在帮助读者掌握面向对象编程的核心思想。编程题是检验理解并深化理论...
在C#编程语言的学习过程中,第五章通常会深入讲解面向对象编程的核心概念和技术。面向对象编程(Object-Oriented Programming,OOP)是C#的基础,也是软件开发中的重要思维方式。这一章的内容可能会涵盖以下几个关键...
在C++编程领域,第五章通常会涉及到C++的核心概念和关键特性,这些知识点对于深入理解和熟练运用C++至关重要。本章可能涵盖了类与对象、封装、继承、多态等面向对象编程的基础知识,也可能涉及模板和异常处理等进阶...
【北大青鸟 ACCP5.0 S2 C# 第五章课后阶段和作业答案】是针对北大青鸟教育机构的ACCP5.0第二学期(S2)C#编程课程第五章的学习材料,旨在帮助学生巩固和检验他们在该章节所学的知识。这章可能涵盖了C#语言的核心概念...
第五章通常会深入讲解Swing的一些核心概念和常用组件。 在Swing中,主要的组件包括按钮(Button)、文本框(TextField)、标签(Label)、滚动面板(ScrollPane)、菜单(MenuBar)、对话框(Dialog)等。这些组件使得开发者...
5. **第五章继承**:继承是面向对象编程的重要特性,它允许一个类(子类)继承另一个类(父类)的属性和方法,实现代码重用和扩展性。 6. **第六章多态**:多态性使不同的对象能够响应同一种消息,增强了程序的灵活...
第五章 继承、接口与泛型 第六章 字符串和正则表达式 第七章 常用实用类 第八章 线程 第九章 输入输出流 第十章 基于Swing的图形的用户界面设计 第十一章 Java中的网络编程 第十二章 Java与数据库操作 第十三章 Java...
《C++ Primer》是一本经典的C++学习教程,第五版是该书的最新版本,涵盖了C++11至C++14标准的最新特性。在IT行业中,掌握C++的重要性不言而喻,因此,这本书以及它的习题集被许多程序员和开发者用作学习和提升技能的...
这份资料主要涵盖了C++第五章的内容,这一章节通常涉及到更高级的编程技巧,如类和对象的深入应用、继承与多态等核心概念。 首先,让我们详细讨论一下C++中的类和对象。类是C++面向对象编程的基础,它定义了一组...
第五章 继承与派生是面向对象编程的关键概念,继承使一个类(子类或派生类)可以继承另一个类(基类)的属性和行为。这提供了代码复用和层次结构的设计,同时支持多态性。 第六章 多态性与虚函数是C++实现动态绑定...