与类中this关键字相似,Java语言中使用关键字super表示父类对象。通过在子类中使用super做前缀可以引用被子类隐藏的父类变量或被子类重写的父类方法。虽然构造方法不能够继承,但利用super关键字,子类构造方法中也可以调用父类的构造方法。
1.操作被隐藏的变量和方法
若成员变量x和方法y()分别是被子类隐藏的父类的变量和方法,则:
super.x //表示父类的成员变量x
super.y() //表示父类的成员方法y()
【例7-6】利用supers操作父类被隐藏和重写的变量和方法。
//********** ep7_6.java **********
class ep7_6_a{
int n;
float f(){
float sum=0;
for(int i=1;i<=n;i++){
sum=sum+i;
}
return sum;
}
}
class ep7_6_b extends ep7_6_a{
int n;
float f(){
float c;
super.n=n;
c=super.f();
return c/n;
}
float g(){
float c;
c=super.f();
return c/2;
}
}
class ep7_6{
public static void main(String args[]){
ep7_6_b aver=new ep7_6_b();
aver.n=100;
System.out.println("result_one="+aver.f());
System.out.println("result_two="+aver.g());
}
}
运行结果:
result_one=50.5
result_two=2525.0
2.使用super调用父类的构造方法
子类不能继承父类的构造方法,若子类想使用父类的构造方法,必须在子类的构造方法中利用super来调用,且super必须是子类构造方法中的第一条语句。
【例7-7】利用supers操作父类的构造方法。
//********** ep7_7.java **********
class ep7_7_student{
int num;
String name;
ep7_7_student(int num,String name){
this.num=num;
this.name=name;
System.out.println("姓名:"+name+"\n学号:"+num);
}
}
class ep7_7_univer extends ep7_7_student{
boolean 婚否;
ep7_7_univer(int num,String name,boolean b){
super(num,name);
婚否=b;
System.out.println("婚否:"+婚否);
}
}
class ep7_7{
public static void main(String args[]){
ep7_7_univer student_one=new ep7_7_univer(1234,"小强",false);
}
}
运行结果:
姓名:小强
学号:1234
婚否:false
需要注意的是,若子类调用父类的构造方法,在子类的构造方法中省略掉super关键字,则系统默认有“super()”,即调用父类不带参数的构造方法。由于Java语言规定如果一个类中含有一个或多个构造方法,系统不提供默认的构造方法(不含参数的构造方法),所以当在父类中定义了多个构造方法时,应考虑包括一个不带参数的构造方法,以防止子类省略super关键字时出现错误。
在默认情况下,所有的成员变量或成员方法都可以被隐藏或重写,如果父类的成员不希望被子类的成员所隐藏或重写则将其声明为final。
用final修饰成员变量,说明该成员变量是最终变量,即为常量。程序中的其他部分可以访问,但不能够修改。用final修饰成员方法,则该方法不能再被子类所重写,即该方法为最终方法。
【例7-8】final用法举例。
//********** ep7_8.java **********
class ep7_8_a{
static final double pi=3.1415926; //声明静态常量
public final void f(){ //声明最终方法
System.out.println("pi="+pi);
}
}
class ep7_8_b extends ep7_8_a{
private int num=100;
public void f(){ //出错,不可覆盖父类的最终方法
System.out.println("num="+num);
}
}
class ep7_8{
public static void main(String args[]){
ep7_8_b One=new ep7_8_b();
One.f();
}
}
由于父类方法f已经被声明为final,所以在子类ep7_8_b中对f方法重写出现错误。变量pi被声明为final所以子类也不能继承该变量。
如果一个类被final关键字修饰,说明这个类不能再被其他类所继承,该类被称为最终类。
需要注意的是:
l 所有被private声明为私有的方法,以及包含在final类中的方法都被默认为是最终的。
l 用static和final两个关键字修饰变量时,若不给定初始值,则按照默认规则对变量初始化。若只用final修饰而不用static,就必须且只能对该变量赋值一次,不能默认。
7.1.5Object类是Java程序中所有类的直接或间接父类,处在类的最高层次。一个类在声明时若不包含关键字extends,系统就会认为该类直接继承Object类。Object类包含了所有Java类的公共属性和方法,这些属性和方法在任何类中均可以直接使用,其中较为主要的方法如表7-1所示。
表7-1 Object类常用方法
|
方法 |
方法说明 |
|
public Boolean equals(Object obj) |
比较两个类变量所指向的是否为同一个对象,是则返回true |
|
public final Class getClass() |
获取当前对象所属类的信息,返回Class对象 |
|
public String toString() |
将调用toString()方法的对象转换成字符串 |
|
protected Object clone() |
生成当前对象的一个备份,并返回这个副本 |
|
public int hashCode() |
返回该对象的哈希代码值 |
下面主要介绍equals方法和getClass方法的使用。
1.equals方法的使用
【例7-9】使用“==”运算符和equals方法比较对象的异同。
//********** ep7_9.java **********
class ep7_9_a{
int x=1;
}
class ep7_9{
public static void main(String args[]){
ep7_9_a One=new ep7_9_a();
ep7_9_a Two=new ep7_9_a();
String a1,a2,a3="abc",a4="abc";
a1=new String("abc");
a2=new String("abc");
System.out.println("a1.equals(a2)是"+(a1.equals(a2)));
System.out.println("a1==a2是"+(a1==a2));
System.out.println("a1.equals(a3)是"+(a1.equals(a3)));
System.out.println("a1==a3是"+(a1==a3));
System.out.println("a3.equals(a4)是"+(a3.equals(a4)));
System.out.println("a3==a4是"+(a3==a4));
System.out.println("One.equals(Two)是"+(One.equals(Two)));
System.out.println("One==Two是"+(One==Two));
One=Two;
System.out.println("赋值后,One.equals(Two)是"+(One.equals(Two)));
System.out.println("赋值后,One==Two是"+(One==Two));
}
}
运行结果:
a1.equals(a2)是true
a1==a2是false
a1.equals(a3)是true
a1==a3是false
a3.equals(a4)是true
a3==a4是true
One.equals(Two)是false
One==Two是false
赋值后,One.equals(Two)是false
赋值后,One==Two是true
从例7-9中可以看出,对于字符串变量来说,使用“==”运算符和“equals()”方法来比较,其比较方式是不同的:“==”运算符用于比较两个变量本身的值,即两个对象在内存中的首地址;“equals()”方法比较的是两个字符串中所包含的内容是否相同。对于非字符串类型的变量来说,“==”运算符和“equals()”方法都用来比较其所指对象在堆内存中的首地址,即比较两个类类型的变量是否指向同一个对象。对于a3和a4这两个由字符串常量生成的变量,其所存放的内存地址是相同的。
2.getClass方法的使用
【例7-10】getClass方法返回调用该方法所属的类。
//********** ep7_10.java **********
class ep7_10_a{
protected String name;
public ep7_10_a(String a){
name=a;
}
}
class ep7_10{
public static void main(String args[]){
ep7_10_a One=new ep7_10_a("abc");
Class b=One.getClass(); //用变量b调用getClass()方法
System.out.println("对象One所属的类为:"+b);
}
}
运行结果:
对象One所属的类为:class ep7_10_a
getClass方法返回值是Class类型,所以在例7.10中通过声明一个Class类型的变量b来接收它。