上一小节详细阐述了Java语言中方法重写的相关知识。很多读者都会问:方法可以被重写,属性是否也能被重写呢?在此首先澄清一个概念:当子类中定义了一个属性,并且该属性的名称与父类中的某个属性名称相同,这种情况并不叫做“重写”或“覆盖”,而是被称为“屏蔽”。
Java语言允许子类用名称相同的属性去屏蔽父类的某个属性。子类在屏蔽父类属性时有如下几个语法特点:
一、子类属性可以重新设置属性的默认值,例如:
class A{
int x = 1;
}
class B extends A{
int x = 5;
}
在以上代码中定义了两个类A和B,其中B是A的子类。父类A中所定义的属性x默认值是1,而子类B中所定义的同名属性屏蔽了A类中的x,其默认值也被重新设置为5,这种重新设置属性默认值的情况并不会引起语法错误。而当子类B的某个方法中调用属性x时,将会调用到子类B中的x,也即值为5的那个x。如果在B类的方法中希望调用到A类所定义的属性x,也需要在它的前面加上super关键字,语法格式如下:
super.属性名称 |
二、子类属性可以与父类属性类型不同,例如:
class A{
int x = 1;
}
class B extends A{
double x = 5.0;
}
以上代码中,父类A所定义的属性x是int型,而子类B所定义的同名属性x是double型,虽然属性类型发生了变化,但这种情况并不会引起语法错误。如果B有一个子类C,那么C类将会继承double型的x而不是int型的x。当然,C类也可以重新定义一个其他类型的属性x屏蔽掉B类中x。总之,子类所定义的属性并不会被其父类同名属性的类型所限制。
三、final关键字并不能阻止父类属性被屏蔽,例如:
class A{
final int x = 1;
}
class B extends A{
int x = 5;
}
以上代码中,父类A所定义的属性x被final关键字所修饰,但子类B仍然可以定义一个同名属性x,并且重新设置其默认值。有读者会问:为什么父类中的方法前面加上final关键字就能阻止方法被重写,但属性前面加上final关键字就不能阻止属性被屏蔽呢?这是因为final关键字用于方法之前和属性之前的作用不同而导致的。final关键字出现在方法之前,其作用是阻止子类重写该方法。而final关键字出现在属性之前,其作用是使得该属性的值不能被修改,成为一个常量,但并不能阻止该属性被子类所屏蔽。子类如果屏蔽了父类中带有final关键字的属性,并且在子类中这个属性的前面没有final关键字,那么在子类中这个属性的值是可以被修改的。
通过以上三个语法特点可以看出:所谓属性的屏蔽,本质上就是子类对父类某个属性的重新定义。也就是说,无论父类定义的属性是什么类型,其默认值是多少,有没有被final关键字所修饰,子类都可以对该属性进行重新定义。重新定义的属性与父类中原本的属性相比,它的类型、默认值都可以不相同。当然,子类如果有“后代”,那么这些“后代”将会继承到重新定义之后的属性,除非它再次对该属性进行重新定义。
除此文字版教程外,小伙伴们还可以点击这里观看我在本站的视频课程学习Java。