练习一
有父类Base,内部定义了x、y属性。有子类Sub,继承自父类Base。子类新增了一个z属性,并且定义了calculate方法,在此方法内计算了父类和子类中x、y、z属性三者的乘积。请补全子类构造方法的初始化逻辑,使得该计算逻辑能够正确执行。
输入描述:
三个整数:x, y, z
输出描述:
三个整数的乘积:x*y*z
本题主要考察在继承关系上,构造方法的使用。
- 当子类继承父类之后,要先帮助父类进行成员的初始化,此时需要通过super关键字来实现。
- 同时初始化子类自己的成员。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextInt()) {
int x = scanner.nextInt();
int y = scanner.nextInt();
int z = scanner.nextInt();
Sub sub = new Sub(x, y, z);
System.out.println(sub.calculate());
}
}
}
class Base {
private int x;
private int y;
public Base(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
class Sub extends Base {
private int z;
public Sub(int x, int y, int z) {
//write your code here
super(x,y);
this.z = z;
}
public int getZ() {
return z;
}
public int calculate() {
return super.getX() * super.getY() * this.getZ();
}
}
练习二
A 派生出子类 B , B 派生出子类 C ,并且在 java 源代码有如下声明:
1. A a0=new A();
2. A a1=new B();
3. A a2=new C();
问以下哪个说法是正确的?()
A.只有第一行能通过编译
B.第1、2行能通过编译,但第3行编译出错
C.第1、2、3行能通过编译,但第2、3行运行时出错
D.第1行,第2行和第3行的声明都是正确的
本题描述的代码如下:
class A {
}
class B extends A {
}
class C extends B {
}
public class Test {
public static void main(String[] args) {
A a0=new A();//1
A a1=new B();//2
A a2=new C();//3
}
}
主要疑问就是注释3处,此时A虽然不是C的直接父类,但是C依然间接继承了A的内容的,此时可以发生向上转型的。
练习三
以下代码运行结果
class Base {
Base() {
System.out.print("Base");
}
}
public class Alpha extends Base {
public static void main( String[] args ) {
new Alpha();//1
//调用父类无参的构造方法
new Base();//2
}
}
A.Base
B.BaseBase
C.编译失败
D.代码运行但没有输出
E.运行时抛出异常
继承关系上的执行顺序。
当子类继承父类之后,在实例化子类对象的时候,先要调用父类的构造方法,来帮助父类初始化。上述代码相当于如下代码:
class Base {
Base() {
System.out.print("Base");
}
}
public class Alpha extends Base {
Alpha() {
super();
}
public static void main( String[] args ) {
new Alpha();//1
//调用父类无参的构造方法
new Base();//2
}
}
编译器会默认提供如上的子类的构造方法。
所以,注释1处输出的结果为Base,注释2处输出的结果为:Base
最终结果是BaseBase。故:选择B;
练习四
以下程序的输出结果
class Base{
public Base(String s){
System.out.print("B");
}
}
public class Derived extends Base{
public Derived (String s) {
System.out.print("D");
}
public static void main(String[] args){
new Derived("C");
}
}
A.BD
B.DB
C.C
D.编译错误
当子类继承父类需要先初始化继承过来的父类的成员,此时需要通过super来完成。很明显在子类的构造方法当中,并没有通过super调用父类的构造方法。正确写法应该是:
class Base{
public Base(String s){
System.out.print("B");
}
}
public class Derived extends Base{
public Derived (String s) {
super(s);
System.out.print("D");
}
public static void main(String[] args){
new Derived("C");
}
}
练习五
class X{
Y y=new Y();//1
public X(){//2
System.out.print("X");
}
}
class Y{
public Y(){//3
System.out.print("Y");
}
}
public class Z extends X{
Y y=new Y();//4
public Z(){//5
System.out.print("Z");
}
public static void main(String[] args) {
new Z();
}
}
本题考察代码的执行顺序:
类Z继承类X。
在继承层次上,先执行父类和子类的静态的,再执行父类的实例,父类的构造,最后执行子类的实例和子类的构造。
根据以上顺序,我们得出结论:本题中没有静态的。所以先执行1和2,再执行4和5。执行注释1和注释4的时候,分班打印Y。故最终的结果是YXYZ。
练习六
以下关于关键字super的描述中,正确的是:
A.super关键字只代表当前对象内部的那一块父类型特征,不包含在子类对象中
B.super关键字不仅可以指代子类的直接父类,还可以直接指代父类的父类
C.子类通过super关键字只能调用父类的方法,而不能调用父类的属性
D.子类通过super关键字只能调用父类的属性,而不能调用父类的方法
本题中主要考察关键字super。首先3种用法为:
1.super.data访问父类中的属性
2.super.func() 访问父类的方法
3.super() 访问父类的构造方法
根据这3点,选项C和D均错。
B中:super只能指代其直接父类,不能指代父类的父类
A正确,super关键字只是在代码层次上提高了代码的阅读性。在子类中代表继承过来的父类型的特征。通过super.data就能知道访问的是父类的data。
练习七
以下代码输出结果
public class Person{
private String name = "Person";
int age=0;
}
public class Child extends Person{
public String grade;
public static void main(String[] args){
Person p = new Child();
System.out.println(p.name);
}
}
本题主要考察继承和访问修饰限定符private
子类继承父类之后,会继承父类私有的数据,但是由于private访问修饰符的问题,子类没有办法直接反问该数据。
练习八
在 java 中,一个类可同时定义为许多同名的方法,这些方法的形式参数个数,类型或顺序各不相同,传回的值可能各不相同,这种面向对象的特性称为(c)
A.隐藏
B.重写
C.重载
D.无此特性
练习九
以下说法, 描述错误的是:B
A.重载要求两个方法名字相同, 但是参数的类型和个数不同, 不要求返回值类型相同
B.重写要求两个方法名字相同, 同时参数的类型和个数相同, 不要求返回值类型相同
C.重写的方法可以使用 @Override 注解来修饰
D.父类的方法为 private 的时候, 子类方法不能进行重写.
练习十
以下代码输出 BD
class B {
public int Func() {
System.out.print("B");
return 0;
}
}
class D extends B {
@Override
public int Func() {
System.out.print("D");
return 0;
}
}
public class Test {
public static void main(String[] args) {
B a = new B();
B b = new D();
a.Func();
b.Func();
}
}