final关键字
final关键字可用于修饰类、变量和方法,他有“无法改变”或者“最终”的含义,因此被final修饰的类、变量和方法将具有以下特性
1)final修饰的类不能被继承
2)final修饰的方法不能被子类重写
3)final修饰的变量(成员变量和局部变量)是常量,只能赋值一次。
注意:使用final关键字修饰成员变量时,虚拟机不会对其进行初始化,因此使用final修饰成员变量时,需要在定义变量的同时赋予一个初始值。
抽象类(abstract)和接口(interface)
抽象类
当定义一个类时,常常需要定义一些方法来描述该类的行为特征,但有时这些方法的实现方式是无法确定的。所以Java允许在定义方法时不写方法体。不包含方法体的方法为抽象方法,抽象方法必须用abstract关键字来修饰。使用abstract关键字来修饰的类为抽象类。
在定义抽象类时需注意,包含抽象方法的类必须声明为抽象类,但抽象类可以不包含任何抽象方法,只需使用abstract关键字来修饰即可。另外抽象类是不可被实例化的,因为抽象类中有可能包含抽象方法,抽象方法是没有方法体的,不可以被调用。如果想调用抽象类中的抽象方法,则需要创建一个子类,在子类中将抽象类中的抽象方法进行实现。
运行结果抽象类可以有构造方法,只是不能直接创建抽象类的实例对象而已。
接口(interface和implements)
如果一个抽象类中所有方法都是抽象的,则可以将这个类用另外一种形式来定义,即接口。接口是由常量和抽象方法组成的特殊类,是对抽象类的进一步抽象。
在定义接口时,需要使用interface关键字来声明,其语法格式如下。
[ public ] interface 接口名 [ extends 接口1,接口2… ]{
[ public ] [ static ] [ final ] 数据类型 常量名 = 常数值;
[ public ] [ abstract ] 返回值 抽象方法名(参数列表);
}
在语法中,一个接口可以有多个父接口,它们之间用逗号隔开。java使用接口的目的是为了克服单继承的限制,因为一个类只能有一个父类,而一个类可以实现多个接口。接口中的变量默认使用“public static final”来修饰,即全局变量;接口中定义的方法默认使用“public abstract”来修饰,即抽象方法,如果接口声明为public,则接口中的变量和方法全部为“public”。
由于接口中的方法都是抽象方法,因此不能通过实例化对象的方法来调用接口中的方法。此时需要定义一个类,并使用implements关键字实现接口中的所有方法。一个类可以在继承另一个类的同时实现多个接口,这些接口在implements子句中要使用英文逗号(,)隔开。接口的实现类声明格式如下。
接口 运行结果[ 修饰符 ] class < 类名 > [ extends <超类名> ] [ implements < 接口1 >,< 接口2 >…… ]
从运行结果可以看出,类Dog实现了Animal接口后是可以被实例化的,并且实例化后就可以调用Dog方法。需要注意的是,一个类实现一个接口,必须给出接口中的所有方法的实现,如果不能实现某方法,也必须写出一个空方法。
接口的特点归纳:
1)接口中的方法都是抽象的,不能实例化对象
2)接口中的属性只能是常量
3)当一个类实现接口时,如果这个类是抽象类,则实现接口中的部分方法即可,否则需要实现接口中的所有方法。
4)一个类通过implements关键字实现接口时,可以实现多个接口,被实现的多个接口之间要用逗号隔开,具体实例如下
interface Run{
程序代码……
}
interface Fly{
程序代码……
}
class Bird implements Run,Fly{
程序代码
}
5)一个接口可以通过extends关键字来继承多个接口,接口之间要用逗号隔开,如下
interface Running{
程序代码……
}
interface Flying{
程序代码……
}
Interface Eating extends Runing,Flying{
程序代码……}
6)一个类在继承另一个类的同时还可以实现接口,此时,extends关键字必须位于implements关键字之前,具体如下。
class Dog extends Canidae implements Animal{
}
多态(instansof)
什么是多态
在设计一个方法时通常希望该方法具备一定的通用性。
在同一个方法中,由于参数类型的不同而导致执行效果各异的现象就是多态,继承是多态得以实现的基础。
在Java中,为了实现多态,允许使用一个父类类型的变量来引用一个字类类型的对象,根据被引用子类对象特征的不同,得到不同的运行结果。
多态 运行结果当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
多态不仅解决了方法同名的问题,而且还使程序变得更加灵活,从而有效地提高了程序的可扩展性和可维护性。
对象的类型转换
将子类对象当做父类类型来使用,这种情况在java中称为“向上转型”,例如下面两行代码
Animal a1=new Cat( ); //将Cat对象当做Animal类型来使用
Animal a2=new Dog( ); //将Dog对象当做Animal类型来使用
将子类对象当做父类来使用时不需要任何显示地声明,需要注意的是,此时不能通过父类类型变量去调用子类中特有的方法。
类型转换 运行结果在animalShout()方法中将Animal类型的变量强转为Cat类型。
这种将父类类型当做子类类型使用的情况,在java中被称为“向下转型”。
instanceof
它可以判断一个对象是否为某个类(或接口)的实例或子类实例。
对象(或者对象引用变量) instanceof 类(或接口)
对上面代码中的animalShout()方法进行修改
instanceofObject类
在JDK中提供了一个Object类,它是类层次的根类,每个类都直接或间接继承自该类,所有对象(包括数组)都实现了这个类的方法。Object类中的常用方法如下表。
第10行代码调用了Animal对象的toString()方法,虽然Animal类中并没有定义这个方法,但程序并没有出错。这是因为Animal默认继承自Object类,在Object类中定义了toString()方法,在该方法中输入了对象的基本信息,Object类的toString()方法中的具体代码如下。
getClass( ).getName( ) + " @ " + Integer.toHexString(hashCode()) ;
getClass( ).getName( ) 代表返回对象所属类的类名,即Animal。
hashCode()代表返回该对象的哈希值
Integer.toHexString(hashCode()) 代表将对象的哈希值用十六进制表示
其中,hashCode( )是Object类中定义的一个方法,这个方法将对象的内存地址进行哈希值运算,返回一个int类型的哈希值。
在实际开发中,通常希望对象的toString()方法返回的不仅仅是基本信息,而是一些特有的信息。这时重写Object的toString()方法便可实现。
匿名内部类
在类里面定义的类称为内部类(inner Class),内部类是外部类的一个成员。Java内部类可以分为成员内部类、方法内部类和匿名内部类。
前面多态的讲解中,如果方法的参数被定义为一个接口类型,那么就需要定义一个类来实现接口,并对该接口进行对象的实例化。除此之外,还可以用匿名内部类来实现接口。所谓匿名内部类就是没有名字的内部类,表面上看去似乎有名字,实际上那并不是它的名字。当程序中使用匿名内部类时,在定义匿名内部类的地方往往直接创建该类的一个对象。
下面使用匿名内部类来实现,匿名内部类的格式
new 父类 (参数列表)或接口(){
//匿名内部类实现部分
}
在调用animalShout方法时,在方法的参数位置上写new Animal(){ },这相当于创建了一个实例对象,并将对象作为参数传给animalShout方法。在new Animal()后面有一对大括号,表示创建的对象为Animal的子例实例,该子例是匿名的。
网友评论