(一)学习总结
1.阅读下面程序,分析是否能编译通过?如果不能,说明原因。应该如何修改?程序的运行结果是什么?为什么子类的构造方法在运行之前,必须调用父 类的构造方法?能不能反过来?
class Grandparent {
public Grandparent() {
System.out.println("GrandParent Created.");
}
public Grandparent(String string) {
System.out.println("GrandParent Created.String:" + string);
}
}
class Parent extends Grandparent {
public Parent() {
System.out.println("Parent Created");
super("Hello.Grandparent.");
}
}
class Child extends Parent {
public Child() {
System.out.println("Child Created");
}
}
public class Test{
public static void main(String args[]) {
Child c = new Child();
}
}
结果:不能编译通过。
原因及修改方式:super关键字可以从子类中调用父类中的构造方法,但语句必须放在子类构造方法的首行。
运行结果:
GrandParent Created.String:Hello.Grandparent.
Parent Created
Child Created
此程序中的Parent类继承了Grandparent类,在继承操作中,子类对象实例化之前必须首先调用父类中的构造方法为父类中的属性初始化再调用子类中的构造方法。所以不能呢个将其反过来。此外,在这个程序中的super语句调用的是Grandparent类的有参构造方法,所以输出为GrandParent Created.String:Hello.Grandparent.。
2.阅读下面程序,分析程序中存在哪些错误,说明原因,应如何改正?正确程序的运行结果是什么?
class Animal{
void shout(){
System.out.println("动物叫!");
}
}
class Dog extends Animal{
public void shout(){
System.out.println("汪汪......!");
}
public void sleep() {
System.out.println("狗狗睡觉......");
}
}
public class Test{
public static void main(String args[]) {
Animal animal = new Dog();
animal.shout();
animal.sleep();
Dog dog = animal;
dog.sleep();
Animal animal2 = new Animal();
dog = (Dog)animal2;
dog.shout();
}
}
错误一:animal.sleep(); 没有为类Animal定义sleep()方法。发生向上转型关系后,所调用的方法一定是被子类覆写过的方法,所以去掉sleep()方法。
错误二:Dog dog = animal; 类型不匹配,不能从Animal转换为Dog。改成Dog dog=(Dog)animal。
3.运行下列程序
class Person {
private String name ;
private int age ;
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
}
public class Test{
public static void main(String args[]){
Person per = new Person("张三",20) ;
System.out.println(per);
System.out.println(per.toString()) ;
}
}
(1)程序的运行结果如下,说明什么问题?
Person@166afb3
Person@166afb3
原因:对象输出时会调用Object类中的toString方法,直接输出函数名默认调用toString方法。
(2)那么,程序的运行结果到底是什么呢?利用eclipse打开println(per)方法的源码,查看该方法中又调用了哪些方法,能否解释本例的运行结果?
源码:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
该方法调用了getClass()方法,getName()方法, Integer.toHexString()方法。
所以最后返回了类名+@字符+引用地址。
(3)在Person类中增加如下方法
public String toString(){
return "姓名:" + this.name + ",年龄:" + this.age ;
}
重新运行程序,程序的执行结果是什么?说明什么问题?
姓名:张三,年龄:20
姓名:张三,年龄:20
在Person类中覆写了toString方法,所以调用的是覆写后的方法。
4.汽车租赁公司,出租汽车种类有客车、货车和皮卡三种,每辆汽车除了具有编号、名称、租金三个基本属性之外,客车有载客量,货车有载货量,皮卡则同时具有载客量和载货量。用面向对象编程思想分析上述问题,将其表示成合适的类、抽象类或接口,说明设计思路。现在要创建一个可租车列表,应当如何创建?
(1)定义一个抽象类“出租汽车”,抽象方法承载量,定义客车类、货车类、皮卡类去继承出租汽车,实现抽象类中的抽象方法。
(2)客车类定义属性及构造方法,打印载客量,货车实现抽象方法,打印载货量,皮卡实现抽象方法,打印载客量和载货量。
(3)定义租车类,声明一个数组,通过构造方法初始化。
5.阅读下面程序,分析代码是否能编译通过,如果不能,说明原因,并进行改正。如果能,列出运行结果
interface Animal{
void breathe();
void run();
void eat();
}
class Dog implements Animal{
public void breathe(){
System.out.println("I'm breathing");
}
void eat(){
System.out.println("I'm eating");
}
}
public class Test{
public static void main(String[] args){
Dog dog = new Dog();
dog.breathe();
dog.eat();
}
}
不能编译通过。因为Dog类必须实验抽象类中的方法run();在Dog中的方法,默认是public abstract 所以在子类实现抽象方法时,应该用public修饰。
6.总结
1.接口:
接口与类的不同在于:
(1) 没有变量的声明,但可以定义常量。
(2) 只有方法的声明,没有方法的实现。
2.接口中没有自身的构造方法。
3.在接口中定义的常量必须是pubilc static final,这是系统默认的规定,所以常量也可以没有任何修饰符。
接口中只有方法声明,而无方法实现,接口中声明的方法必须是public abstract,也是系统默认的规定。
4.在类中实现接口所定义的方法时,方法的声明必须与接口中所定义的完全一致。
在类中实现接口所定义的方法时,必须显式地使用public修饰符,否则将被系统警告为缩小了接口中定义的方法的访问控制范围。
抽象类可以不实现接口的抽象方法,而非抽象类必须实现接口中的所有方法。
5.接口和抽象类的区别
1)抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
2)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
3)接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
4)一个类只能继承一个抽象类,而一个类却可以实现多个接口。
(二)实验总结
- 实验四一:
程序设计思路:一个银行类,一个用户交易类。
银行类:声明属性,构造方法,相应的get,set方法。静态方法welcome():打印欢迎语,存款方法,取款方法,静态方法welcomeNext():输出欢迎下次光临。
交易类:对银行类实例化后,调用其相应方法。 - 实验四二:程序设计思路:四个类
定义员工类,具有姓名、年龄、性别属性,并具有构造方法和toString方法。
定义管理层类,继承员工类,有自己的属性职务和年薪。
定义职员类,继承员工类,并有自己的属性所属部门和月薪。
测试类中,对对象进行实例化。 - 实验四三:程序设计思路:一共九个类
定义立体和平面的抽象类,里面包括两个抽象方法。求体积和表面积,周长。
其它形状的类分别继承立体和平面的抽象方法,重写抽象类中的方法,再写toString方法。 - 实验四四:程序设计思路:六个类
Feeder类中使关于饲养员的相关信息和属性。
定义Animal抽象类,里面有一个抽象方法表示饲养员已经喂过这个动物了。
让动物类继承这个抽象类,覆写里面的方法。
测试类中对Feeder对象进行实例化。并调用喂动物的函数。 - 实验五一:程序设计思路:一共五个类
定义一个接口Pet。Pet类中有抽象方法。
Pet是 Cat类和Dog类的接口,覆写Pet中的抽象方法,并定义自己的属性和相应的构造方法和set,get方法,toString方法。
PetShop类中定义一个对象数组存放所有宠物,并为其开辟空间。有一个购买宠物方法,显示所有宠物的所有信息的方法。 - 实验五二:程序设计思路:一共四个类
(1)接口Animal:有2个抽象方法cry()和getAnimaName()。
(2)模拟器类Simulator:有一个playSound(Animal animal)方法。即参数animal可以调用实现Animal接口类重写的cry()方法播放具体动物的声音、调用重写的getAnimalName()方法显示动物种类的名称。
(3)实现Animal接口的Dog类和Cat类
(4)测试类:main方法中包含如下代码:
Simulator simulator = new Simulator();
simulator.playSound(new Dog());
simulator.playSound(new Cat()); - 实验五三:程序设计思路:
- 1)一个抽象类交通工具类Transportation,属性:编号,型号,运输负责人。方法:无参构造和含三个参数的构造方法,get和set方法,抽象方法transport()
- 2)定义一个专用运输车类JDTransportation继承交通工具类,继承父类构造方法,实现transport()方法,输出一个运输信息。
- 3)定义一个接口GPS实现对货物的定位。接口中有方法showCoordinate()跟踪货物的位置信息。
- 4)定义一个类Phone实现GPS接口
- 5)定义一个快递任务类SendTask,具有私有属性:快递单号、货物重量。方法:无参和含参构造方法,get和set方法,
sendBefore()方法输出运输前的检查信息和快递单号。
send(Transportation t,GPS tool)方法输出运货人、车辆编号、型号信息,该方法中调用transport方法输出运输信息,调用showCoordinate()方法输出货物位置坐标。sendAfter( Transportation t )方法输出货物运输完成后的信息。
- 6)定义一个测试类,创建一个快递任务类对象,一个交通工具类对象,一个GPS工具对象。模拟物流快递过程。输出运输前、运输中和运输后的信息。 - 实验五四:程序设计思路:
将实验三的第四题中的时间类删除,原本的时间类数据生日、工作时间用Date类替换,用comparable和comparator接口Arrays类的sort方法排序后输出。
(三)代码托管
(https://gitee.com/hebau_java_cs16/Java_CS01FHY/tree/master/ex03)