Java语言程序设计 习题第十一章
11.2章节习题
11.1 下面说法是真是假? 一个子类是父类的子集
不是,子类可以拥有父类的数据域和方法,还可以拥有自己独有的数据域和方法
11.2 使用什么关键字来定义一个子类?
extends
11.3 什么是单一继承?什么是多重继承? Java支持多重继承吗?
单一继承是一个子类只能有一个父类
多重继承是一个子类可以有多个父类
Java不支持多重继承。在Java中,一个子类只能有一个父类,但是一个父类可以有多个子类
11.3章节习题
11.4 下面a中类C的运行结果输出什么? 编译b中的程序的时候将出现什么问題?
class A {
public A() {
System.out.println("A's no-arg constructor is invoked");
}
}
class B extends A {
//B类虽然没有构造方法,但是编译器会自动创建一个无参构造方法
//public B() {
//同时,由于B没有明确的调用父类A的构造方法,super()也会被默认的构建出来,去调用A的无参构造方法
//super();
//}
}
public class Test {
public static void main(String[] args) {
//调用B类的无参构造方法来创建实例
B b = new B();
}
}
输出结果:
A's no-arg constructor is invoked
class A {
public A(int x) {
}
}
class B extends A {
//编译器默认加了super(),想要去调用A类的无参构造方法,但是A类没有无参构造方法,所以报错
public B() {
}
}
public class C {
public static void main(String[] args) {
B b = new B();
}
}
11.5 子类如何调用它的父类的构造方法?
使用关键字super
11.6 下面的说法是真是假: 当从子类调用构造方法时,它的父类的无参构造方法总是会被调用?
假,如果子类明确的调用了父类的有参构造方法,那么父类的无参构造方法就不会再被调用
11.4章节习题
11.7 下面说法是真是假:可以重写父类中定义的私有方法?
假,子类重写父类中的私有方法实际上是新定义了一个方法,和父类方法没有关系
11.8 下面说法是真是假:可以重写父类中定义的静态方法?
假,只能重写有访问权限的非private方法
11.9 如何从子类中显式的调用父类的构造方法?
使用super()
11.10 如何从子类中调用一个被重写的父类的方法?
使用super.method()
11.5章节习题
11.11 指出下面代码的错误:
public class Test {
private double radius;
//需要一个无参构造方法供B类中的构造方法来调用
//public Test() {
//}
public Test(double radius) {
//需要使用关键字this来指向数据域,不然就是局部变量了
radius = radius;
}
public double getRadius() {
return radius;
}
public double getArea() {
return radius * radius * Math.PI;
}
}
class B extends Test {
private double length;
B(double radius, double length) {
//父类的字段是private,不可以直接访问,需要使用super关键字来调用父类的构造方法来访问字段
Test(radius);
//需要使用关键字this来指向数据域,不然就是局部变量了
length = length;
}
@Override
public double getArea() {
return getArea() * length;
}
}
11.12 解释方法重载和方法重写的不同之处。
对于方法重写,首先必须保证方法签名和返回值都相同,只有方法体是不同的,其次需要保证必须是子类重写了父类的方法,在Java中提供了@Override来检测是否重写了父类。
对于方法重载,首先只要返回值(大多数情况)和方法名相同即可,方法参数和方法体都可以不同;其次可以重载同一个类或父类的方法。
11.13 如果子类中的方法具有和它父类中的方法完全相同的方法签名,且返回值类型也相同,那么这是方法重写还是方法重载呢?
Override
11.14 如果子类中的一个方法具有和它父类中的方法完全相同的方法签名,但返回值类型不相同,这会存在问题吗?
会
11.15 如果子类中的一个方法具有和它父类中的方法相同的名字,但参数类型不同,那么这是方法重写还是方法重载呢?
Overload
11.16 使用@Override标注的好处是什么?
在Java中提供了@Override来检测是否重写了父类。
11.8章节习题
11.17 什么是多态? 什么是动态绑定?
多态意味着子类可以安全地进行向上转型,即子类型的实例对象可以指向父类型的引用变量;
动态绑定意味着实例对象调用实例方法时,是基于运行时实际的实例对象类型来调用的,并不是基于引用变量的声明类型
11.18 描述方法匹配和方法绑定之间的不同。
方法匹配:只要方法名,参数类型、数量、顺序一致,就可以根据引用变量的类型去匹配方法
方法绑定:运行时期才能决定实例对象的类型并用这个类型的实例去匹配方法
11.19 可以将以下实例赋值给Object[]类型的变置吗,new int[50]、new Integer[50]、new String[50] 或者 new Object[50]?
New int[50]不行,其他都可以
11.20 下面代码中哪里有错误?
public class Test {
public static void main(String[] args) {
Integer[] list1 = {
12, 24, 55, 1};
Double[] list2 = {
12.4, 24.0, 55.2, 1.0};
int[] list3 = {
1, 2, 3};
printArray(list1);
printArray(list2);
//在调用printArray()方法时,传入了一个int数组,但是该方法只接受一个Object数组作为参数,因此会导致编译错误。在Java中,int是一个基本类型,不属于某一个类或包,不是一个对象,而Integer是一个对象。在Java中,基本类型和对象类型之间不能自动转换。
printArray(list3);
}
public static void printArray(Object[] list) {
for (Object o: list)
System.out.print(o + " ");
System.out.println();
}
}
11.21 给出下面代码的输出。
public class Test {
public static void main(String[] args) {
new Person().printPerson();
new Student().printPerson();
}
}
class Student extends Person {
@Override
public String getInfo() {
return "Student";
}
}
class Person {
public String getInfo() {
return "Person";
}
public void printPerson() {
System.out.println(getInfo());
}
}
输出结果:
Person
Student
public class Test {
public static void main(String[] args) {
new Person().printPerson();
new Student().printPerson();
}
}
class Student extends Person {
//private字段不可以访问,所以不可以Override
private String getInfo() {
return "Student";
}
}
class Person {
private String getInfo() {
return "Person";
}
public void printPerson() {
System.out.println(getInfo());
}
}
输出结果:
Person
Person
11.22 给出下面程序的输出。
public class Test {
public static void main(String[]args) {
A a = new A(3);
}
}
class A extends B {
public A(int t) {
System.out.println("A's constructor is invoked");
}
}
class B {
public B() {
System.out.println("B's constructor is invoked");
}
}
输出结果:
B's constructor is invoked
A's constructor is invoked
11.23 给出下面程序的输出:
public class Test {
public static void main(String[] args) {
new A();
new B();
}
}
class A {
int i = 7;
//对于new A(),首先会来匹配执行以下代码,并且A直接继承自Object,构造方法继承链终止。setI是方法重写,根据多态,会根据实例对象的实际类型匹配方法,所以会执行A类的setI方法
//(2/2)构造方法继承链至此,执行setI,setI是方法重写,根据多态,会根据实例对象的实际类型匹配方法,所以会执行B类的setI方法
public A() {
setI(20);
System.out.println("i from A is " + i);
}
public void setI(int i) {
this.i = 2 * i;
}
}
class B extends A {
//(1/2)对于new B(),首先会来匹配执行以下代码,并且B直接继承自A,构造方法继承链向上继续
public B() {
System.out.println("i from B is " + i);
}
public void setI(int i) {
this.i = 3 * i;
}
}
输出结果:
i from A is 40
i from A is 60
i from B is 60
11.9章节习题
11.24 下面的说法是对还是错?
• 总可以成功地将子类的实例转换为父类。
对,即为向上转型
• 总可以成功地将父类的实例转换为子类。
错,不一定成功,可以利用instanceof判断
11.25 对于程序清单11-1和程序清单11-2中的GeometricObject类和Circle类,回答下面的问题:
a. 假设circle和object如下创建:
Circle circle = new Circle(1);
GeometricObject object = new GeometricObject();
下面的布尔表达式的值是 true 还是 false ?
//true
(circle instanceof GeometricObject)
//true
(object instanceof GeometricObject)
//true
(circle instanceof Circle)
//false
(object instanceof Circle)
b. 下面的语句能够成功编译吗?
Circle circle = new Circle(5) ;
GeometricObject object = circle;
可以,这是向上转型
c. 下面的语句能够成功编译吗?
GeometricObject object = new GeometricObject();
Circle circle = (Circle)object;
不可以
11.26 假设 Fruit、Apple、Orange、GoldenDelicious 和 Macintosh 如下面的继承层次定义:
假设给出以下代码 :
Fruit fruit = new GoldenDelicious();
Orange orange = new Orange();
回答下面的问题:
a. fruit instanceof Fruit的值为 true 吗?
True
b. fruit instanceof Orange 的值为 true 吗?
False
c.fruit instanceof Apple的值为true吗?
True
d.fruit instanceof GoldenDelicious 的值为 true 吗?
True
e.fruit instanceof Macintosh的值为true吗?
False
f.orange instanceof Orange 的值为 true 吗?
True
g.orange instanceof Fruit 的值为 true 吗?
True
h.orange instanceof Apple 的值为 true 吗?
False
i.假设makeApple Cider方法定义在Apple类中。fruit可以调用这个方法吗?orange可以调用这个方法吗?
都不可以
j.假设makeOrangeJuice方法定义在Orange类中。orange可以调用这个方法吗?fruit可以调用这个方法吗?
orange可以,但是fruit不可以
k.语句 Orange p=new Apple() 是否合法?
不合法
必须要在同一个继承链,才可以进行类型转化
l.语句Macintosh p=new Apple()是否合法?
不合法
需要使用转型括号()来进行转化尝试
m.语句Apple p=new Macintosh()是否合法?
合法
11.27 下面代码中的错误是什么?
public class Test {
public static void main(String[] args) {
Object fruit = new Fruit();
//Fruit实际上是父类,不能把父类变成子类
Object apple = (Apple)fruit;
}
}
class Apple extends Fruit {
}
class Fruit {
}
11.10章节习题
11.28 每个对象都有 toString 方法和 equals 方法吗?它们从何而来?如何使用?重写这些方法合适吗?
都有,从Object来,使用object1.equals(object2);,非常合适
11.29 当覆盖equals方法时,常见的错误就是在子类中输错它的签名。例如:equals 方法被错误地写成equals(Circle circle) , 如下面a中的代码所示;应该使用如b中所示的 equals(Object circle)替换它。分别给出运行a和b中的Test类和Circle类的输出。
public class Test {
public static void main(String[] args) {
Object circle1 = new Circle();
Object circle2 = new Circle();
System.out.println(circle1.equals(circle2));
}
}
a:
class Circle {
double radius;
public boolean equals(Circle circle) {
return this.radius == circle.radius;
}
}
输出结果false
b:
class Circle {
double radius;
public boolean equals(Object circle) {
return this.radius == ((Circle)circle).radius;
}
}
输出结果true
如果 Test 类中的 Object 换成 Circle, 那么分别使用 a 和 b 中的 Circle 类来运行 Test 将输出什么?
都是true
11.11章节习题
11.30 如何实现以下功能?
a.创建一个存储双精度值的 ArrayList。
ArrayList<Double> decimals = new ArrayList<>();
b.向数组列表中追加一个对象。
decimals.add();
c.在数组列表的开始位置插人一个对象。
decimals.add(0, 3.14);
d.找出数组列表中所包含对象的个数。
decimals.size();
e. 从数组列表中刪除给定对象。
decimals.remove(3.14);
f. 从数组列表中删除最后一个对象。
decimals.remove(decimals.size() - 1);
g.检测一个给定的对象是否在数组列表中。
decimal.contains(3.14):
h.从数组列表中获取指定下标位置的对象。
decimal.get(1);
11.31 请找出下面代码中的错误:
ArrayList<String> list = new ArrayList<>(); list.add("Denver");
list.add("Austin");
//已经制定了ArrayList的类型是String,就不可以再上传Date
list.add(new java.util.Date());
String city = list.get(0);
//超过范围了
list.set(3, "Dallas");
System.out.println(list.get(3));
11.32 假定ArrayList list包含{“Dallas”,“Dallas”,“Houston”,“Dallas”}。调用list.remove(“Dallas”)—次之后的列表是什么?下面语句可以从列表中删除所有具有值"Dallas"的元素么?如果不能,修改代码。
for (int i = 0; i < list.size(); i++)
list.remove("Dallas");
如果只调用一次remove,列表会变成{“Dallas”,“Houston”,“Dallas”}
这个语句不可以删除所有Dallas,因为随着不同的Dallas被删除,ArrayList的length是在不断变小的,最后会导致循环提前终止
for (int i = 0; i < list.size(); i++) {
if (list.remove(element))
i--;
}
11.33 解释为什么下面代码显示[1,3],而不是[2,3]。
ArrayList<Integer> list = new ArrayList<>(); list.add(1);
list.add(2);
list.add(3);
list.remove(1); System.out.println(list);
remove(1)移除的不是数字1,而是在数组中index=1的元素
11.34 解释为什么下面代码是错误的。
ArrayList<Double> list = new ArrayList<>();
list.add(1);
1被当成了整数类型
11.12章节习题
11.35 改正下面语句中的错误:
int[] array = {
3, 5, 95, 4, 15, 34, 3, 6, 5};
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(array));
//基本数据类型不可以传递给ArrayList,ArrayList中的元素必须是对象
Integer[] array = {
3, 5, 95, 4, 15, 34, 3, 6