习题解答chapter03
题目
1. Java的访问控制修饰符有哪些?各有什么访问权限?请对照第7页ppt的表格分别写程序验证。
2. 子类对于从父类继承的哪些属性与方法是可见的?请分别写程序进行验证。
3. 什么是组合?有什么作用?请举例说明。
4. 什么是重载?有什么作用?请举例说明。
5. 什么是覆盖?有什么作用?请举例说明。
1. Java的访问控制修饰符有哪些?各有什么访问权限?请对照第7页ppt的表格分别写程序验证。
- default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
- private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
- public : 对所有类可见。使用对象:类、接口、变量、方法
- protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
class test{
private int i;
public int j;
protected int k;
public String name;
private String ID;
protected int age;
public int getI(int i) {
this.i = i;
return i;
}
public int getK(){
return k;
}
public int getJ(){
return j;
}
}
public class AccessControlCodifier {
public static void main(String args[]){
test A = new test();
A.j = 11;
A.k = 12;
// A.i = 10; /* 报错,无法在类外访问私有成员 */
System.out.println("j = " + A.j + "\ni = " + A.getI(9) + "\nk = " + A.k);
// 公有成员和保护成员可以在类外通过对象直接访问,私有成员可以通过类内的get函数访问
}
}
2. 子类对于从父类继承的哪些属性与方法是可见的?请分别写程序进行验证。
子类不能直接继承父类中的 private 属性和方法。
创建一个公共动物父类
public class Animal {
private String name;
private int id;
/*由于name和id都是私有的,所以子类不能直接继承,
需要通过有参构造函数进行继承*/
public int age;
protected String hobby;
public Animal(String my_name,int my_id) {
name = my_name;
id = my_id;
}
public int getAge(int age){
this.age = age;
return age;
}
public void eat() {
System.out.println(name+"正在吃");
}
public void sleep() {
System.out.println(name+"正在睡");
}
public void introduction() {
System.out.println("大家好!我是" +id+"号"+name +",我今年" + age + "岁.");
}
}
子类 Penguin 需要通过关键字 super 进行声明
public class Penguin extends Animal {
private int num;
public Penguin(String myname,int myid) {
super(myname,myid); // 声明继承父类中的两个属性
}
public int getNum(int _num){
this.num = _num;
return num;
}
public void myHobby(String my_hobby){
this.hobby = my_hobby;
System.out.println("我的爱好是" + hobby + "。");
}
public void number(){
System.out.println("我有" + num + "个兄弟。");
}
}
具体通过有参构造函数进行继承
public class PenguinT {
public static void main(String[] args) {
Penguin M = new Penguin("小爱",100);
M.age = 10;//子类继承父类公有属性
// 调用一个有参构造方法
M.eat();
M.sleep();
M.introduction();
M.hobby = "睡觉"; //子类可以继承父类的保护成员并直接使用
M.myHobby("睡觉");//子类继承
M.getNum(4);
M.number();
}
}
3. 什么是组合?有什么作用?请举例说明
组合是通过对象内部的属性引用来实现的。
在面向对象程序设计之所以有比面向过程设计有较大的影响力,其中一个关键就是具有“高内聚,松耦合”的特点。组合会使对象之间的耦合性较为松散。
以下面代码作为例子进行分析
class FighterPlane {
String name;
int missileNum;
public FighterPlane(String _name, int _missleNum) {
this.name = _name;
this.missileNum = _missleNum;
}
public void fire() {
if (this.missileNum > 0) {
System.out.println("now fire a missile !");
this.missileNum -= 1;
} else {
System.out.println("No missile left !");
}
}
}
class A {
FighterPlane fp;
public A(FighterPlane fpp) {
this.fp = fpp; //A对象中拥有了FighterPlane对象的引用
}
public void invoke() {
//A对象发送消息给FighterPlane的对象
System.out.println(fp.name);
}
}
public class Run {
public Run() {
}
public static void main(String[] var0) {
FighterPlane ftp = new FighterPlane("su35", 10);
//产生A对象,并将ftp作为对象引用传入
A a= new A(ftp);
a.invoke();
}
}
引用fp将对象和FighterPlane对象组合起来:A对象和FighterPlane对象虽然在内存中是两个对象,但是由于A中拥有FighterPlane对象的引用,就可以把A对象看成是由FighterPlane对象组合而成的。
组合会使对象之间的耦合性较为松散,因为A对象通过引用向FighterPlane对象发送消息从而使A和FighterPlane产生相互关联,这种联系是建立在FighterPlane的授权基础上的,FighterPlane对象的私有属性和私有方法A是无法访问的。因而,消息和内部私有方法之间就没有直接联系,这就为阻断变化在软件内部之间传播提供了可能。
4. 什么是重载?有什么作用?请举例说明。
Java中提供了两种多态机制——重载和覆盖。在类中定义了多个同名不同内容参数的成员方法时称这些方法为重载(overloading),返回类型可以相同也可以不同。
重载规则:
- 被重载的方法必须改变参数列表(参数个数或类型不一样);
- 被重载的方法可以改变返回类型;
- 被重载的方法可以改变访问修饰符;
- 被重载的方法可以声明新的或更广的检查异常;
- 方法能够在同一个类中或者在一个子类中被重载。
- 无法以返回值类型作为重载函数的区分标准。
public class Overloading {
public int test(){
System.out.println("test1");
return 1;
}
public void test(int a){
System.out.println("test2");
}
//以下两个参数类型顺序不同
public String test(int a,String s){
System.out.println("test3");
return "returntest3";
}
public String test(String s,int a){
System.out.println("test4");
return "returntest4";
}
public static void main(String[] args){
Overloading o = new Overloading();
System.out.println(o.test());
o.test(1);
System.out.println(o.test(1,"test3"));
System.out.println(o.test("test4",1));
}
}
5. 什么是覆盖?有什么作用?请举例说明。
子类对父类参数相同,返回值类型也相同的同名方法进行重新定义,这种多态被称为覆盖(ocerriding)。这使得子类能够根据需要实现父类的方法,是父类和子类之间多态的一种表现。
public class Main {
public static void main(String[] args) throws IOException {
People a=new People();
People b=new Up(6);
a.bark();
b.bark();
System.out.println(((Up)b).level); // 强制类型转换
}
}
class People{
public void bark(){
System.out.println("Hello!");
}
}
class Up extends People{
public int level;
public Up(int lv){
level=lv;
}
public void bark(){
System.out.println("鸽了鸽了,不播了");
}
}
父类的bark方法被子类覆盖,父类变量指向子类实例时可以使用强制类型转换访问父类没有的子类成员。
注意:
- 子类方法覆盖父类方法,子类的访问权限应该大于或等于父类。
- 同名的static方法和非static方法不能相互覆盖。