快速入门Java(三)多态,抽象类,Object,枚举类,反射

一、超类和子类

在Java中,所有的继承都是公有继承,而没有C++中的私有继承和保护继承。

将通用的方法放在超类中,而将具有特殊用途的方法放在子类中。

super不是一个对象的引用,不能将super赋给另一个对象变量,它只是一个指示编译器调用超类方法的特殊关键字。在子类中可以增加方法或覆盖超类的方法,然而绝对不能删除继承的任何域和方法。

子类构造器

由于Manager类的构造器不能访问Employee类的私有域,所以必须利用Employee类的构造器对这部分私有域进行初始化,我们可以通过super实现对超类构造器的调用。使用super调用构造器的语句必须是子类构造器的第一条语句。

如果子类的构造器没有显式地调用超类的构造器,则将自动地调用超类默认(没有参数)的构造器。如果超类没有不带参数的构造器,并且在子类的构造器中又没有显式地调用超类的其他构造器,则
Java编译器将报告错误。

关键字this有两个用途:一是引用隐式参数,二是调用该类其他的构造器。

关键字super也有两个用途:一是调用超类的方法,二是调用超类的构造器。

一个对象变量可以指示多种实际类型的现象被称为多态。在运行时能够自动地选择调用哪个方法的现象被称为动态绑定。

多态

在Java程序设计语言中,对象变量是多态的。一个Employee变量即可以引用一个Employee类对象,也可以引用一个Employee类的任何一个子类的对象(例如,Manager)。

不能将一个超类的引用赋给子类变量。Manager m=staff[i];//Error

如果是private方法,static方法,,final方法或者构造器,那么编译器将准确地知道应该调用哪个方法,我们将这种调用方式称为静态绑定。与此对应的是,调用的方法依赖于隐式参数的实际类型,并且在运行时实现动态绑定。

在覆盖一个方法的时候,子类方法不能低于超类方法的可见性。特别是,如果超类方法是public,子类方法一定要声明为public。

阻止继承:final类和方法
不允许扩展的类被称为final类。类中的特定方法也可以被声明为final。如果这样做,子类就不能覆盖这个方法(final类中的所有方法自动地成为final方法.)

抽象类

为了提高程序的清晰度,包含一个或多个抽象方法的类本身必须被声明为抽象的。
public abstract class Person
{
. . .
public abstract String getDesceiption();
}
除了抽象方法之外,抽象类还可以包含具体数据和具体方法。建议尽量将通用的域或方法(不管是否是抽象的)放在超类(不管是否是抽象类)中。

扩展抽象类可以有两种选择。一种是在抽象类中定义部分抽象类方法或不定义抽象类方法,这样就必须将子类也标记为抽象类;另一种是定义全部的抽象方法,这样一来,子类就不是抽象的了。

抽象类不能被实例化。可以定义一个抽象类的对象变量,但是它只能引用非抽象子类的对象。

受保护访问

在某些时候,人们希望超类中的某些方法允许被子类访问,或允许子类的方法访问超类的某个域。为此,需要将这些方法或域声明为protected。事实上,Java中的受保护部分对所有子类及同一个包中的所有其他类都可见。


二、Object:所有类的超类

在Java中,只有基本类型不是对象,例如,数值,字符和布尔类型的值都不是对象。所有的数值类型,不管是对象数组还是基本类型的数组都扩展了Object类。

equals,hashCode,toString方法

Object类中的equals方法用于检测一个对象是否等于另外一个对象。在Object类中,这个方法将判断两个对象是否具有相同的引用。如果两个对象的状态相等,就认为这两个对象是相等的。

由于hashCode方法定义在Obejct类中,因此每个对象都有一个默认的散列码。其值为对象的存储地址。StringBuffer类中没有定义hashCode方法,它的散列码是由Object类的默认hashCode方法导出的对象存储地址。
在Object中还有一个重要的方法,就是toString方法,它用于返回表示对象值的字符串。

三、泛型数组列表

在Java中,允许在运行时确定数组的大小。
ArrayList是一个采用类型参数的泛型类。
使用get和set方法实现访问或改变数组元素的操作。

四、对象包装器与自动装箱

有时,需要将int这样的基本类型转换为对象。所有的基本类型都有一个与之对应的类。例如,Integer类对应基本类型int。通常,这些类称为包装器(wapper)。对象包装器类是不可变的,即一旦构造了包装器,就不允许更改包装在其中的值。同时,对象包装器还是final,因此不能定义它们的子类。

由于每个值分别包装在对象中,所以ArrayList的效率远远低于int[]数组。

下面这个调用list.add(3);将自动地变换成list.add(Integer.valueOf(3));这种变换被称为自动装箱。相反地,当将一个Integer对象赋值给一个int值时,将会自动地拆箱。另外·,如果在一个条件表达式中混合使用Integer和Double类型,Integer值就会拆箱,提升为double,再装箱为Double。

五、参数数量可变的方法

printf方法是这样定义的:

     public classPrintStream {
      public PrintStream printf(String  fmt,Obbject . . . args){return    format(fmt,args);}
              }

这里的省略号…是Java代码的一部分,它表明这个方法可以接收任意数量的对象(除fmt参数之外)。实际上,printf方法接收两个参数,一个是格式化字符串,另一个是Object[]数组,其中保存着所有的参数。

六、枚举类

public enum Size{SMALL,MEDIUM,LARGE,EXTR_LARGE};
实际上,这个声明定义的类型是一个类,它刚好有4个实例。如果需要的话,可以在枚举类型中添加一些构造器,方法和域。

七、反射

能够分析类能力的程序称为反射。反射机制可以用来:

  • 在运行时分析类的能力。
  • 在运行时查看对象。例如,编写一个toString方法供所有类使用。
  • 实现通用的数组操作代码。
  • 利用Method对象,这个对象很像C++中的函数指针。

八、继承的设计技巧

不要使用受保护的域,protected机制破坏了封装。不过,protected方法对于指示那么不提供一般用途而应在子类中重新定义的方法很有用。使用多态,而非类型信息。使用多态方法或接口编写的代码比使用对多种类型进行检测的代码更加易于维护和扩展。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值