难以置信(java高级编程考试题及答案)Java高级编程学什么,读书笔记-java高级编程之类的设计,java高级程序设计,
面向对象程序设计的三大特性:类的继承,多态,封装
类的继承(Inheritance),它可以在已经声明的类的基础上来声明一个新的类。采用关键字extends标明要继承的类,这样就可以从中继承它的所有属性和方法。新声明的类可以在此基础上根据需要增加新的属性和方法。我们把被继承的类称为父类或超类(superclass),父类也称为基类;把通过继承产生的类称为子类(subclass),子类也称为派生类。类的继承具有传递性,类的继承是有层次关系的。在Java类继承的层次中,java.lang.Object类是所有类的根类(也就是最高层次的父类),所有的java类都直接或间接的继承了java.lang.Object类。如果在类的声明中没有指明extends关键字,则表明其直接父类是Object类。在Object类中事先定义了一些实现和支持面向对象机制的基本方法,如equals、toString等。
Java中类的继承的语法:
<修饰符> class <子类名> [extends <父类名>]{<声明>*}
Java中只支持单继承,即一个类只能有一个父类,但一个父类可以派生出多个子类。Java中只允许单继承的机制有利于简化继承性、避免追溯过程中(例如对于子类对象所调用的某个方法进行合法性检查时)可能出现的混乱,提高代码的运行效率。
访问控制,就是对访问权限的控制。Java中的访问控制是通过在声明类、属性和方法时加上适当的访问控制修饰符来实现的。Java中的访问控制有四种级别,但只有三个访问控制修饰符,当不使用任何一种时,所得到的访问控制级别就是第四种——默认级别。对于属性和方法,所有四种访问控制级别都是适用的,但对于类的访问控制,只有默认访问和公有访问两种情况。
如果在类声明时没有加入任何访问修饰符,则表示该类具有默认访问控制级别。具有默认访问控制级别的类只能被同一个包中的类访问。
如果在类声明时加入了public访问修饰符,则表示该类具有公有访问控制级别。具有公有访问控制级别的类可以被所有类访问,而不管它们是否在同一个包中。如果使用的公有类与你正在编写的类为于不同的包中,需要import导入这个公有类。
如果类自身对于另一个类是不可见的,则即使将其成员都声明为public,也没有一个成员是可见的。因此只有类可见时,其各个成员的访问控制级别才有意义。类成员(包括类的属性和方法)有4种访问控制级别,对应的访问控制修饰符分别为public,private,default,protected(default表示不加任意一个访问控制修饰符)。
类成员的访问控制级别
如果在类成员声明时加入了关键字public,则表明所有的其他类,不管他们属于哪个包,都能够访问该类成员,这类成员即为公有成员。如果类成员被声明为private,则该成员只能被其所在类的内部访问,而该成员所在类之外的其他任何代码都不能访问该成员,这样的成员称为私有成员。子类不能继承其父类的私有成员。
如果在类成员的声明时不加入任何访问控制修饰符,该成员则为默认成员,具有默认访问控制级别——可以在默认成员所在类内部或与该类处于同一个包中的其他类中对该成员进行访问,但位于不同包中的类不能对其进行访问,因此默认访问也称为“包级访问”。保护成员还可以被不同包中的子类(通过继承)访问。包外子类有权访问其父类的保护成员,指的是通过继承来使用该成员,而并不意味着包外子类可以使用父类实例的引用来访问该保护成员。这里所说的保护是建立在继承关系上的,保护不是指子类能够处理受保护的父类对象,就像它是公有的那样,而是说子类只能通过继承访问受保护的成员。保护成员被继承后,该成员在该子类中实际上已经变成了私有的,即一旦包外子类继承了父类的保护成员,该成员对于这一子类之外的任何代码来说都变成私有的。protected是java中很难理解的访问控制修饰符,应该只在非常特殊的情况下使用它。访问控制修饰符(public、private、protected)是不能用于修饰局部变量的(如方法中的变量)。
Java中引入访问控制机制的目的在于实现信息的隐藏和封装,在使用过程中需根据实际需要使用合适的访问控制级别。一般只有当某个属性或方法必须被其他无关的类直接访问时才将它声明为公有的,否则在能满足使用要求的前提下,一般将类成员(特别是类的实例变量)声明为private或protected。可以将不需要外部访问的属性设计为private,然后对外提供获取和修改它们的方法。
子类对父类进行扩充,增加一些父类没有的属性和方法,这是继承的一种常见情况。继承的另一种情况是子类对父类进行改造,比如重新定义父类中已经定义了的方法,这就是方法的重写。简单地说,方法的重写(override)指的是子类重写父类的方法,以实现不同于父类的功能,重写也称为覆盖。
方法重写的规则:1方法名必须与被重写的方法一样;2参数列表必须与被重写的方法一样;3返回类型必须与被重写的方法一样;4访问控制级别不能比被重写的方法严格。
如果在子类中对父类的方法进行了重写,这时如果需要访问父类中原来的方法,可以使用super关键字来实现(super.成员名),它的含义是引用父类中的成员(可以是属性或方法)。
多态(Polymorphism)是面向对象程序设计的又一重要特征。所谓多态,简单说就是指对象的多种形态。
一个子类继承了父类,则子类就具有了父类所具有的属性和方法,因此一个子类对象也可以看成是一个父类对象,这就保证了在程序中任何父类对象出现的地方都可以用子类对象来代替,这就是多态。
如果将一个子类对象赋值给一个父类类型的引用变量(引用变量在内存中只是占用一定长度的引用空间,该内存空间中记录的是所指对象的句柄——对象的地址,在这里引用变量地址空间中保存的是子类对象的地址),则在编译时系统把它当成一个父类类型的引用变量看待。因此通过该引用变量只能访问父类中声明过的属性和方法,子类中增加的成员被隐藏了——这就是“编译时的多态性”。实际上我们说的多态指的是变量的多态而非对象的多态,一个对象只能有一种形式,这在调用构造器创建对象时就已经确定了,但是一个引用变量可以指向不同形式的对象,因此它是多态的。
声明为父类类型的引用变量即使实际引用的是子类类型的对象,也只能访问父类中声明过的属性和方法,对于子类中增加的成员是不能访问的。但如果子类中对父类中声明过的方法进行了重写,调用的是重写后的子类的方法,因为编译时是父类类型,运行时引用的是子类对象。这时多态在运行时表现出来的一个重要特性,称为虚方法调用。它指的是方法调用时,获得的是运行时与变量类型(也就是该变量实际引用的对象类型)相关的行为,而不是编译时与变量类型相关的行为。重写方法的访问控制级别不能比被重写的方法弱。
虚方法调用的规则,在运行时,JVM是根据实际对象的类型动态地选择调用哪个方法的。必须保证重写方法的访问控制级别不能比被重写的方法严格,否则将导致编译出错。实际上,在虚方法调用中,使父类引用子类对象成为可能的条件是,子类必须保证能够做父类可以做的任何事情。
如果成员方法出现重写,引用的是子类方法;如果成员变量出现隐藏(意思是子类中定义了和父类相同的变量),引用的是父类变量。对于虚方法调用,子类重写了父类方法,引用的是运行时实际对象类型的行为,即子类方法;但变量引用的是父类的变量。
多态参数,指的是可以编写参数类型为父类类型的方法,调用时它可以接受其子类的对象作为实参。多态参数结合instanceof操作符,可以让编写的方法针对不同的实际对象类型进行不同的处理。instanceof操作符用于判断一个引用变量是否是某种类型,语法格式为<引用变量> instanceof <引用类型>,它是一个布尔表达式。当instanceof左边的引用变量所引用的实际对象类型是instanceof右边给出的引用类型或其子类类型时,整个表达式返回true,否则返回false。
强制对象类型转换只有将父类类型的对象转换为其子类类型的对象,才能保证编译通过。将子类类型的对象转换为其父类类型的对象是系统默认的类型转换(conversion),不需要进行强制转换,可以通过简单的赋值运算完成。
在有些情况下,需要在同一个类中(或其子类中)定义多个同名的方法,这些方法完成类似的功能,只通过参数的不同来区分它们,这就是重载(overload)。重载有两种情况,普通方法的重载和构造器的重载。
方法重载遵循一定的规则:1重载方法的参数列表必须和被重载的方法不同,并且这种不同必须足以清楚地确定调用哪一个方法;2重载方法的返回类型可以和被重载的方法相同,也可以不同,但是只有返回类型不同是不够的;3重载方法可以改变访问控制级别。
如果调用的是带对象引用(参数是对象的引用)的重载方法,情况会复杂一些。说明,决定调用哪个重载方法并不是在运行时动态决定的,而是在编译时确定的。引用类型(而不是对象类型)决定调用哪个重载方法。
构造器作为一种特殊的方法,也可进行重载。当声明了多个构造器后,创建新对象时可以根据参数的不同决定调用哪个构造器,以提供不同的实例化方法。构造器重载时可以在构造器代码的第一行使用this关键字,可以调用同一个类中的其他构造器,这样可以节省重复性代码,同时在this调用之后还可以有其他的初始化代码。
构造器是不能被继承的,因此要调用父类构造器,必须在子类构造器代码的第一行使用super关键字,以调用父类相应的构造器(参数必须匹配),用于完成子类对象的部分初始化工作。
在创建子类对象时,利用super调用实际上是借用父类的构造器来完成子类对象的部分初始化工作,初始化的还是子类对象的值,而并非运行父类的构造器创建了一个父类对象——这是和使用new调用构造器的区别。另外,super调用所带的参数的列表必须和父类中已经定义的构造器相匹配,如果父类中没有定义相应参数的构造器,则在子类中不能使用对应的supper调用。
使用this和super调用,可以在一个构造器中显式地调用另外一个构造器,这也是显式调用构造器的唯一方法。换句话说,显式调用构造器的唯一方法是从另一个构造器之内调用。在构造器中使用this和super调用时,遵循以下规则:1如果在构造器中显式使用this或super调用,两者不能同时出现,并且this或super调用必须位于构造器代码的第一行,在其后可以有其他的初始化代码。2如果在构造器中没有显式使用this关键字调用重载的其他构造器,也没有使用super关键字调用父类的构造方法,则系统默认调用父类的无参构造器,也即super()。此时如果父类中没有无参构造器,则编译会出错。
this和super关键字用途比较
本文系作者 @河马 原创发布在河马博客站点。未经许可,禁止转载。
暂无评论数据