Java第七章继承、多态、抽象类和接口


Bird bird=new Pigeon();    //某只鸽子是一只鸟    
Pigeon pigeon=(Pigeon) bird;    //通过强制类型转换,告诉编译器“某只鸟就是一只鸽子”    
修改为如下代码:

Bird bird= new Bird();    //某只鸽子是一只鸟    
Pigeon pigeon=(Pigeon)bird;    //通过强制类型转换,告诉编译器“某只鸟就是一只鸽子”
7.4 使用instanceof关键字判断对象类型
当在程序中执行向下转型操作时,如果父类对象不是子类对象的实例,发ClassCatException异常,所以在执行向下转型之前需要养成一个良好的习惯,就是判断父类对象是否为子类对象的这个判断通常使用instancof关字成。使用instanceof关键字判是否一个类实现了某个口(行),也可以用来判断一个实例对象是否属于一个类。
instanceof的语法格式如下:

 

myobject instanceof ExampleClass

使用instanceof关键字的表达式返回值为布尔值。如果返回值为true,说明myobject对象为 ExampleClass的实例对象;如果返回值为false,说明myobject对象不是ExampleClass的实例对象。
误区警示
instanceof是Java语言的关键字,Java 语言中的关键字都为小写。

下面来看一个例子

【例7.7】分析几何图形之间的继承关系
创建 Quadrangle 四边形类、Square 正方形类和Circular 圆形类。其中,Square 类继承 Quadrangle类,在主方法中分别创建这些类的对象,然后使使用instanceof关键字判断它们的类型并输出结果。
class Quadrangle {}
class Square extends Quadrangle{} class Circular { }
public class Demo5 {
public static void main(String args){
Quadrangleq=new Quadrangle();    //四边形对象    
Square s=new Square();    //正方形对象    
System.out.println(q instanceof Square    );    //判断四边形是否为正方形的子类    
System.out.println(s instanceof Quadra    angle);    //判断正方形是否为四边形的子类
System.out.println(q instanceof circular);  //判断正方形是否为圆形的子类
}
}
在运行这道题前,会报错,因为四边形类与圆形类没有继承关系,所以不能用关键词,正确结果如下

false
true
7.5    方法的重载    
在第6章中我们曾学习过构造方法,知道构造方法的名称由类名决定,所以构造方法只有一个名称。如果希望以不同的方式来实例化对象,就需要使用多个构造方法来完成。由于这些构造方法都需要根据类名进行命名,为了让方法名相同而形参不同的构造方法同时存在,必须用到方法重载。虽然方法重载起源于构造方法,但它也可以应用到其他方法中。本节将讲述方法的重载。
方法的重载就是在同一个类中允许存在一个以上的同名方法,只要这些方法的参数个数或类型不同即可。为了更好地解释重载,来看下面的实例。

【例7.8】编写不同形式的加法运算方法(实例位置:资源包\TM\sI\7\8)
创建OverLoadTest类,在该类中编写add)方法的多个重载形式,然后在主方法中分别输出这些方法的返回值。
public class OverLoadTest{
public static int add(int a, int b){    //定义一个方法    
return a + b;}
public static double add(double a, double b){    //与第一个方法名称相同、参数类型不同    
return a + b;
public static int add(int a){    //与第一个方法参数个数不同    
return a;
}
public static int add(int a, double b){    //先int参数,后double参数    
//输出int参数值
return a;
public static int add(double a, int b){    //先double参数,后int参数    
return b;    //输出int参数值    
public static void main(String args) {
System.outprintin("调用add(int,int)方法:"+add(1,2));
System.out.println("调用add(doubledouble)方法:"+add(2.1,3.3)); 
System.out.printin("调用add(int)方法:"+add(1));
System.out.printin("调用add(int,double)方法:"+add(5,8.0)) 
System.outprintin("调用add(doubleint)方法:"+add(5.0,8));
}
}
 

运行结果如下:
调用add(int,int)方法:3
调用add(doubledouble)方法:5.4调用add(int)方法:1
调用add(int,double)方法:5调用add(doubleint)方法:8
在本实例中分别定义了5个方法,在这5个方法中,前两个方法的参数类型不同,并且方法的返回值类型也不同,所以这两个方法构成重载关系;前两个方法与第3个方法相比,第3个方法的参个数少于前两个方法,所以这3个方法也构成了重载关系;最后两个方法相比,发现除了参数的出顺序不同,其他都相同,同样构成了重载关系。

参数个数可以确定两个方法是否具有重载关系时,会想到定义不定长参数方法。不定长方法的语法如下:
返回值 方法名(参数数据类型…参数名称)
如果将上述代码放在例7.8 中,关键代码如例 7.9所示。

【例7.9】使用不定长参数重载加法运算方法(实例位置:资源包\TM\s1\79)
创建 OverLoadTest2类,该类编写add法的多种重载形式,并编写该方法的不定长参数式。然后在主方法中调用这些重载方法,并输出返回值。
public class OverLoadTest2{
public static int add(int a, int b){
return a + b;
public static double add(double a, double b) {
return a + b;}
public static int add(int a) {
return a;
public static int add(int a, double b) {
return a;
public static int add(double a, int b) {
return b;
public static int add(int …. a) {    //定义不定长参数方法    
ints=0;
for (int i = 0; i < a.length;i++) {    //根据参数个数做循环操作    
s += a[1);    //将每个参数累加    
}
return s;    //将计算结果返回    
public static void main(String args[){
System.out.printin("调用add(intint)方法:"+add(1,2));
System.out.printin("调用add(double,double)方法:"+add(2.1,3.3)); System.out.printn(”调用add(int)方法:"+add(1));
System.out.printin("调用add(int,double)方法:"+add(5,8.0)); System.out.printin("调用add(double,int)方法:"+add(5.0,8));
//调用不定长参数方法
System.out.printin("调用不定长参数方法:"+add(1,2,3,4,5,6,7,8,9)) System.out.printin("调用不定长参数方法:"+add(1));
}

调用add(int,int)方法:3
调用add(doubledouble)方法:5.4
调用add(int)方法:1
调用add(intdouble)方法:5
调用add(double,int)方法:8
调用不定长参数方法:45
调用不定长参数方法:1
在上述实例中,在参数列表中使用“…”形式定义不定长参数,其实这个不定长参数a就是一数组,编译器会将“int…a”这种形式看作是“int]a”,所以在add方法体做累加操作时使用到了循环语句,在循环中是根据数组a的长度作为循环条件的,最后将累加结果返回。

7.6final关键字
final被翻译为最后的,最终的,final是Java关键字,凡是被final关键字修饰过的内容都是不可改变的。

7.6.1final变量
final关键字可用于变量明,一旦该变量被设定,就不可以再改变该变量的值。通常,由finalg义的变量为常量。例如,在类中定义PI值,可以使用如下语句:

final double P/=3.14;
当在程序中使用到PI这个常量时,它的值就是3.14。如果在程中再次对定义为final的常量赋值编译器将不会接受。
final关键字定义的变量必须在声明时对其进行赋值操作。final除了可以修饰基本数据类型的常量还可以修饰对象引用。由于数组也可以被看作一个对象来引用,所以final可以修饰数组。一旦一个对象引用被修饰为final后,它就只能恒定指向一个对象,无法将其改变以指向另一个对象。一个既是stat又是final的字段只占据一段不能改变的存储空间。为了深入了解 final 关键字,来看下面的实例。

【例7.10】定义不允许被修改的常量m(实例位置:资源包\TM\sI\7\10)创建FinalData类,该类中定义表示圆周率的常量PI,并尝试修改PI的值。
public class FinalData{   //调用方法
static final double P/=3.1415926;   //定义类型
public static void main(Stringargs){   //主函数
System.outprintln("圆周率的值为:"+PI);
System.outprintln("半径为3的圆的周长为:"+(2*3*PI));//尝试修改PI的值 PI=31415927;
}
7.6.2 final 方法
将方法定义为 final类型,可以防止子类修改父类的定义与实现方式,同时定义为final的方法的执行效率要高于非final方法。在修饰权限中曾经提到过private修饰符,如果一个父类的某个方法被设置为private,子类将无法访问该方法,自然无法覆盖该方法。也就是说,一个定义为private的方法隐式被指定为final类型,因此无须将一个定义为private的方法再定义为final类型。例如下面的语句:

private final void test(){
…//省略一些程序代码}
【例7.11】使用final关键字为电视机上儿童锁(实例位置:资源包\TM\sl\7\11)
创建Dad爸爸类,给Dad类定义一个打开电视机的方法,该方法使用final关键字修饰。创建Dad类的子类Baby 类,让Baby类尝试自己重写打开电视的方法。
class Dad {  //创建类
public final void turnOnTheTV(){  //调用方法
System.outprintn("爸爸打开了电视);  //输出
class Baby extends Dad {   //继承方法
public final void turnOnTheTV(){   //调用方法
System.out.printin("宝宝也要打开电视”);}  //输出
本实例在运行之前,Eclipse 就会报出如图 7.8所示的编译错误。因为打开电视这个方法是由final修饰 的,子类无法重写。所以 Baby 想要打开电视,就只能找爸爸来打开了。

7.6.3final类
定义为final的类不能被继承。如果希望一个类不被任何类继承,并且不允许其他人对这个类进行任何改动,可以将这个类设置为final类。final 类的语法如下:
final 类名{}

如果将某个类设置为final类,则该类中的所有方法都被隐式设置为final方法,但是final类中的成员变量可以被定义为final或非final形式。

7.7多态
利用多态可以使程序具有良好的扩展性,并可以对所有类对象进行通用的处理。在7.3节中已经习过子类对象可以作为父类的对象实例使用,这种将子类对象视为父类对象的做法称为“向上转假如现在要编写一个绘制图形的方法draw,如果传入正方形对象就绘制正方形,如果传入圆对象就绘制圆形,这种场景可以使用重载来实现,定义如下:

public void draw(Square s){    //绘制正方形的方法    
public void draw(Circular c){    //绘制圆形的方法    
但是这种写法有个问题:正方形和圆形都是图形,这场景细分的重载方式不仅增加了代码量,还降低了“易用度”。如果定义一个图形类,让它处理所有继承该类的对象,根据“向上转型”原则可以使每个继承图形类的对象作为draw方法的参数,然后在draw方法中做一些限定就可以根据不同图形类对象绘制相应的图形。这样处理能够很好地解决代码冗余问题,同时程序也易于维护。

【例7.12】万能的绘图方法(实例位置:资源包\TMsI\7\12)    创建 Shape图为Squareirular形类父类创m6,并在该类    
创建一个绘图用的draw0方法,参数为Shape类型,Shape子类对可以作为方法的参并且方法会根据参数的类型绘制相应的图形。
class Shape{}
class Square extends Shape {)    //图形类    
class Circular extends Shape{)
//正方形类继承图形类
public class Demo6{
//圆形类继承图形类
public static void draw(Shape s){    //绘制方法    
if(s instanceof Square){    //如果是正方形    
System.out.printin(“绘制正方形);
} else if (s instanceof Circular){    //如果是圆形    
System.out.printn(“绘制圆形”);
} else {    //如果是其他类型    
System.out.printin("绘制父类图形);}
}
public static void main(Stringargs){
draw(new Shape()); draw(new Square()); draw(new Circular());

运行结果如下:绘制父类图形
绘制正方形
绘制圆形
从本实例的运行结果中可以看出,以不同类对象为参数调用draw0方法,可以处理不同的图形绘制问题。使用多态节省了开发和维护时间,因为程序员无须在所有的子类中定义执行相同功能的方法,避免了大量重复代码的编写。同时,只要实例化一个继承父类的子类对象,即可调用相应的方法,如果需求发生了变更,只需要维护一个draw()方法即可。

Java语言每一个类只能继承一个父类

子类  父类  祖父类

继承 extends

父类 和普通类写法相同

public class 父类类名{

}

子类 需要继承父类

public class 子类类名 extends 父类类名{

}

所有类的构造方法第一行都有一个隐藏的“super();”

作用是在执行该构造方法之前调用其父类构造方法

object类

方法的重写

返回参数相同 方法名相同  传入参数相同  方法体不同

向上转型:将子类对象赋值给父类引用(需要进行自动类型转换)

animal a=new  dog

向下转型:将父类对象赋值给子类引用(需要进行强制类型转换)

dog a=(dog) new animal

方法的重载

方法名相同  参数不同 

final

final修饰变量----常量

final修饰方法----不可以被重写

final修饰类-------不可以被继承 

instanceof

对象名 instanceof 类名   

判断该对象是否属于该类或其子类


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值