1.实验:利用IDE的debug功能给例6.4和例6.6的new语句设置断点,使用单步调试(step into/step over)跟踪子类对象实例化(初始化)的执行顺序,并总结该过程。
例6.4
class AddClass
{
public int x=0,y=0,z=0;
AddClass (int x)
{ this.x=x; }
AddClass (int x,int y)
{ this(x); this.y=y; } //调用第一个构造方法
AddClass (int x,int y,int z)
{ this(x,y); this.z=z; } //调用第二个构造方法
public int add()
{return x+y+z; }
}
public class SonAddClass extends AddClass
{ int a=0,b=0,c=0;
SonAddClass (int x)
{ super(x); a=x+7; }
SonAddClass (int x,int y)
{ super(x,y); a=x+5; b=y+5; }
SonAddClass (int x,int y,int z)
{ super(x,y,z); a=x+4; b=y+4; c=z+4;}
public int add()
{System.out.println("super:x+y+z="+super.add());
return a+b+c;
}
public static void main(String[] args)
{ SonAddClass p1=new SonAddClass (2,3,5);
SonAddClass p2=new SonAddClass (10,20);
SonAddClass p3=new SonAddClass (1);
System.out.println("a+b+c="+p1.add());
System.out.println("a+b="+p2.add());
System.out.println("a="+p3.add());
}
}
输出结果为:
super:x+y+z=30
a+b=40
super:x+y+z=1
a=8
例6.6
class Pare
{
int i =3;
Pare(){}
};
class Construct extends Pare
{
int i=8;
Construct(){}
Construct(int num){this();}
int getSuper(){return super.i;};
public static void main(String[] args){
Construct ct = new Construct(9);
System.out.println(ct.i);
System.out.println(ct.getSuper());
}
}
输出结果为:
8
3
子类对象实例化的执行顺序:
- 为对象分配内存空间,对成员变量进行默认的初始化 。
- 绑定构造方法,将new对象中的参数传递给构造方法的形式参数。
- 调用this 或super语句,注意二者必居其一,但不能同时存在。
- 进行实例变量的显式初始化操作。
public class A{
int value =4;//显式初始化
B b=new B();//显式初始化,注意b引用了B类的一个对象
}
- 执行当前构造方法体中的程序代码。
2. 如何实现两个对象之间互发消息,请举例说明。
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class myApplet extends Applet implements KeyListener
{
private TextField input;
private double d=0.0;
/**
进行初始化工作,产生对象,加入监听者
*/
public void init()
{
input = new TextField(10);
//myApplet是容器,input是组件,调用add使input嵌入容器
add(input);
input.addKeyListener(this);
}
public void paint(Graphics g)
{
g.drawString("您输入了数据"+d,10,50);
}
public void keyPressed(KeyEvent e)
{}
public void keyReleased(KeyEvent e)
{
//首先得到Double类的对象,之后调用对象方法doubleValue得到值
d=Double.valueOf(input.getText()).doubleValue();
//进行刷新,调用paint()方法
repaint();
}
public void keyTyped(KeyEvent e)
{}
}
如上例,MyApplet实现ActionListener这个接口,所以他就是监听者,当然还需要告诉源文件TextField对象input(它是接口的使用者),哪个监听者对这个事件感兴趣,这需要调用input的addActionListener方法进行注册,由于注册对象就是MyApplet,所以用this来指代。当在input中输入数字并回车,系统根据input中注册的信息,MyApplet对象收到消息并在方法中进行字符串到数字的转化以及刷新工作。
3. 谈谈组合与继承的区别以及两者的使用场景(即什么时候宜用组合?什么时候宜用继承?)。
继承是子类继承父类的属性和方法,组合是通过对象内部的属性引用,一个类把另一个类当作组件来用。
组合:需要保证类的安全性,不破坏封装,一个类只作为另一个类的组件。
继承:两个类具有发展关系,一个类是另一个类的具象化,是另一个类的特例。
4. Java中的运行时多态的含义是什么?有什么作用?请举例说明。
运行时多态指的是执行期间判断引用对象的实际类型,根据实际类型判断并调用相应的属性和方法。体现了一个类本身的多态性,使代码具有良好的拓展性。
例如:
class Parent {
public int getScore(){
return 3;
}
public String getCountryName(){
return "China";
}
}
class Son extends Parent {
public int getScore(){
return 4;
}
}
public class RunSon{
public static void main(String args[]){
Son s = new Son();
System.out.println(s.getScore());
System.out.println(s.getCountryName());
}
}
5. 使用接口改写例6.8中的程序。
public interface Shapes
{
double getArea();
double getPerimeter();
void show();
}
public class Circle implements Shapes
{
private int m;
public Circle(int _m) {
m=_m;
}
public double getArea()
//Math是java.lang包中的类,PI是静态其属性,其值为Π
{return(m* m *Math.PI);}
public double getPerimeter()
{return(2*Math.PI* m);}
public void show()
{
System.out.println("Circle Area:" + getArea());
System.out.println("Circle Perimeter:" + getPerimeter());
}
}
public class Rect implements Shapes
{
private int k;
private int m;
public Rect(int width,int height){
k=width;
m=height;
}
public double getArea()
{ return(k*m); }
public double getPerimeter()
{ return(2*k+2*m);}
public void show() {
System.out.println("Rect Area:" + getArea());
System.out.println("Rect Perimeter:" + getPerimeter());
}
}
public class Triangle implements Shapes
{
private int x,y,z,m;
public Triangle(int xx,int yy, int zz){
x=xx;
y=yy;
z=zz;
m=(x+y+z)/2;
}
public double getArea()
{return(Math.sqrt(m*( m-z)*( m-x)*(m-y)));}
public double getPerimeter()
{return 2*m;}
public void show() {
System.out.println("Triangle Area:" + getArea());
System.out.println("Triangle Perimeter:" + getPerimeter());
}
}
import java.applet.Applet;
import java.awt.Graphics;
public class RunShape{
public static void main(String args[])
{
Rect rect=new Rect(5,15);
Triangle tri=new Triangle(5,5,8);
Circle cir =new Circle(1);
rect.show();
System.out.println();
tri.show();
System.out.println();
cir.show();
}
}
6. 简述运算符instanceof的使用场景。
运算符的格式为:“a instanceof A”,其中a为对象的引用,A为类。如果a为A的实例或A的子类实例,则返回true;如果a为A父类的实例,则返回false;如果a对象的类和A没有任何关系,则编译不会通过。