1. 实验:利用IDE的debug功能给代码中的new语句设置断点,使用单步调试(step into/step over)跟踪子类对象实例化(初始化)的执行顺序,并总结该过程。
- 为对象分配内存空间,对成员变量进行默认的初始化
- 绑定构造方法,将new中的参数传递给构造方法的形式参数。
- 调用this或super语句(二者必居其一,不能同时存在),执行流程如图所示
- 进行实例变量的显式初始化操作, 如:
public class A{
int value=4;
B b = new B();
}
- 执行当前构造方法的方法体中的程序代码。
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/e7970db3f463ff5f068583984309f3b4.png#pic_center)
2. 如何实现两个对象之间互发消息,请举例说明。
- 引用必须真实引用了特定的对象,否则会在运行时抛出NullPointerException异常。
- 被访问对象必须定义了相应的属性或方法,否则编译不会通过。
- 被访问的属性或方法必须具有可访问的权限。
class FighterPlane {
private String name;
private int missileNum;
private A a;
public void setA(A _a){
if (_a !=null) { a = _a ;}
}
public A getA(){
if (a !=null)
{ return a;}
else return null;
}
public void fire(){ ……}
public FighterPlane(String _name,int _missileNum){ ……}
}
class A
{
FighterPlane fp;
public A(FighterPlane fpp){
this.fp = fpp;
fpp.setA(this);
}
public void invoke(){
fp.fire();
}
}
public class Run{
public static void main(String[] args)
{
FighterPlane ftp = new FighterPlane("su35",10);
A a = new A(ftp);
a.invoke(); }
}
3. 谈谈组合与继承的区别以及两者的使用场景。
- 组合:在新类里面创建原有类的对象,重复利用已有类的功能。(has-a关系)
class Vehicle{}
class Car entends Vehicle{}
- 继承:可以使用现有类的功能,并且在无需重复编写原有类的情况下对原有类进行功能上的扩展。(is-a关系)
class Tire{}
class Car entends Vehicle{
private Tire t = new Tire();
}
- 使用场景:
- 除非两个类之间是“is-a”的关系,否则不要轻易的使用继承,不要单纯的为了实现代码的重用而使用继承,因为过多的使用继承会破坏代码的可维护性,当父类被修改时,会影响到所有继承自它的子类,从而增加程序的维护难度和成本。
- 不要仅仅为了实现多态而使用继承,如果类之间没有“is-a”的关系,可以通过实现接口与组合的方式来达到相同的目的。设计模式中的策略模式可以很好的说明这一点,采用接口与组合的方式比采用继承的方式具有更好的可扩展性。
- 在Java语言中,能使用组合就尽量不要使用继承。
4. Java中的运行时多态的含义是什么?有什么作用?请举例说明。
- 含义:程序运行时,Java从实例所属的类(new 类)开始寻找匹配的方法执行,如果当前类中没有匹配的方法,则沿着继承关系逐层向上,依次在父类或各祖先类中寻找匹配方法,直到Object类。
- 作用:动态绑定,使用父类引用指向子类对象,再调用某一父类中的方法时,不同子类会表现出不同结果,扩展性极好
public class Test {
public static void main(String[] args) {
Father c = new SonClass();
c.method();
c.method2();
}
}
class Father {
public Father() {
System.out.print("父类的构造方法\t");
}
public void method() {
System.out.print("父类的method()\t");
}
public void method2() {
System.out.print("父类的method2()\t");
}
}
class SonClass extends Father {
public SonClass() {
System.out.print("子类的构造方法\t");
}
@Override
public void method() {
System.out.print("子类的method()\t");
}
}
5. 使用接口改写例6.8中的程序。
package runshape;
public interface Shapes {
public double getArea();
public double getPerimeter();
public void show();
}
package runshape;
public class Circle implements Shapes{
private int r;
public Circle(int r){
this.r=r;
}
public double getArea() {
return Math.PI*Math.pow(r, 2);
}
public double getPerimeter(){
return 2*Math.PI*r;
}
public void show(){
System.out.println("圆形:");
System.out.println("圆的面积是"+this.getArea());
System.out.println("圆的周长是"+this.getPerimeter());
}
}
package runshape;
public class Rect implements Shapes{
private int height;
private int width;
public Rect(int height, int width){
this.height=height;
this.width=width;
}
public double getArea(){
return height*width;
}
public double getPerimeter(){
return 2 * height + 2 * width;
}
public void show(){
System.out.println("矩形:");
System.out.println("矩形的面积是"+this.getArea());
System.out.println("矩形的周长是"+this.getPerimeter());
}
}
package runshape;
public class Triangle implements Shapes {
private int x;
private int y;
private int z;
public Triangle(int x, int y, int z){
this.x=x;
this.y=y;
this.z=z;
}
@Override
public double getArea() {
double m=(x+y+z)/2.0;
return Math.sqrt(m*(m-x)*(m-y)*(m-z));
}
@Override
public double getPerimeter() {
return x+y+z;
}
public void show(){
System.out.println("三角形:");
System.out.println("三角形的面积是"+this.getArea());
System.out.println("三角形的周长是"+this.getPerimeter());
}
}
package runshape;
public class RunShape {
public static void print(Shapes s){
s.show();
}
public static void main(String[] args) {
Rect rect=new Rect(25,25);
Triangle triangle=new Triangle(5,5,8);
Circle circle=new Circle(12);
print(rect);
print(triangle);
print(circle);
}
}
6. 简述运算符instanceof的使用场景。
- 用法:判断对象是否为特定类的实例,还可以将这个对象强制转换成这个类的类型
class Uncle{}
class Pare{}
class Pare1 extends Pare{}
class Pare2 extends Pare1{}
class Pare3 {
public static void main(String[] args){
Uncle u = new Uncle();
Pare p = new Pare();
Pare1 p1 = new Pare1();
Pare2 p2 = new Pare2();
if ( p instanceof Pare)
{System.out.println("p instanceof Pare");}
if (!( p1 instanceof Pare))
{System.out.println("p1 not instanceof Pare");}
else
{System.out.println("p1 instanceof Pare");}
if ( p2 instanceof Pare)
{System.out.println("p2 instanceof Pare");}
if ( p1 instanceof Pare1)
{System.out.println("p1 instanceof Pare1");}
if ( p2 instanceof Pare1)
{System.out.println("p2 instanceof Pare1");}
if ( p1 instanceof Pare2)
{System.out.println("p1 instanceof Pare2");}
else
{System.out.println("p1 not instanceof Pare2");}
if (null instanceof String)
{System.out.println("null instanceof String");}
else
{System.out.println("null not instanceof String");}
}
}