1. 实验:利用IDE的debug功能给例6.4和例6.5的new语句设置断点,使用单步调试(step into/step over)跟踪子类对象实例化(初始化)的执行顺序,并总结该过程。
子类new一个对象时,先执行父类的构造方法,再定义属性,再执行父类构造方法里面的语句,再执行子类的构造方法里面的super语句后面的语句
2. 如何实现两个对象之间互发消息,请举例说明。
class Src
{
int s;
public Src(int _s){//构造函数,保证s的非负
if(_s>=0)
s = _s;
else s=0;
}
public void change(Dis d){//设计一个特殊的方法来改变s的值,每次改变都会给Dis对象发通知
for(int a=1;a<5;a++)
{
d.get();
s=s+a*2;
}
}
}
class Dis
{
Src src;
public Dis(Src s){
this.src = s; //Dis对象中拥有了Src对象的引用
}
public void invoke(){
//Dis中对象发送消息给Src的对象
System.out.println(src.s);
}
public void get()//用来接收通知的方法
{
this.invoke();
}
}
public class Helloworld {
public static void main(String[] args) {
Src src = new Src(5);
//产生Dis对象,并将Src对象引用作为参数传入
Dis dis = new Dis(src);
//发送消息,产生调用关系
dis.src.change(dis);
}
3. 谈谈组合与继承的区别以及两者的使用场景(即什么时候宜用组合 ?什么时候宜用继承?)。
区别:继承是子类对父类的发展,组合是一个类把另一个类当作组件来用。
组合:需要保证类的安全性,不破坏封装,一个类只作为另一个类的组件。
继承:两个类具有发展关系,一个类是另一个类的具象化,是另一个类的特例。
4. Java中的运行时多态的含义是什么?有什么作用?请举例说明。
运行时的多态:一个接口,多个方法
1.父类的引用指向子类对象,掉用的方法是子类的方法
//父类
class A {
void fun()
{
System.out.println(“I am A”);
}
}
//A的子类B
class B extends A
{
void fun()
{
System.out.println(“I am B”);
}
}
//A的子类C
class C extends A
{
void fun()
{
System.out.println(“I am C”);
}
}
class Test
{
public static void main(String[] args)
{
//定义父类对象引用变量
A a;
//子类对象
B b = new B();
C c = new C();
//父类对象引用变量 引用 子类对象
a=b;
a.fun(); //输出 I am B
a=c;
a.fun(); // //输出 I am C
}
}
2.通过接口指向不同的对象来实现不同的方法
//定义接口InterA
interface InterA
{
void fun();
}
//实现接口InterA的类B
class B implements InterA
{
public void fun()
{
System.out.println(“This is B”);
}
}
//实现接口InterA的类C
class C implements InterA
{
public void fun()
{
System.out.println(“This is C”);
}
}
class Test
{
public static void main(String[] args)
{
//定义接口
InterA a;
//接口类型变量引用实现接口的类的对象
a= new B();
a.fun();
a = new C();
a.fun();
}
}
5. 使用接口改写例6.8中的程序。
interface Shapes{
public abstract double getArea();
public abstract double getPerimter();
}
class Rect implements Shapes{
private double x,y;
public Rect(double x,double y){
this.x=x;
this.y=y;
}
public double getArea(){
return x*y;
}
public double getPerimter(){
return 2*(x+y);
}
}
class Triangle implements Shapes{
private double x,y,z,m;
public Triangle(double x,double y,double z){
this.x=x;
this.y=y;
this.z=z;
this.m=x+y+z;
}
public double getArea(){
return(Math.sqrt(m+(m-x)*(m-y)*(m-z)));
}
public double getPerimter(){
return x+y+z;
}
}
class Circle implements Shapes{
private int r;
public Circle(int r){
this.r=r;
}
public double getArea(){
return Math.PI*r*r;
}
public double getPerimter(){
return 2*Math.PI*r;
}
}
public class test{
public static void main(String[] args) {
Rect r=new Rect(10,20);
Triangle t=new Triangle(10, 20, 30);
Circle c=new Circle(10);
printArea(r);
printPerimter(r);
printArea(t);
printPerimter(t);
printArea(c);
printPerimter(c);
/**
Rect Area:200.0
Rect Perimter:60.0
Triangle Area:245.07141816213493
Triangle Perimter:60.0
Circle Area:314.1592653589793
Circle Perimter:62.83185307179586
*/
}
public static void printArea(Shapes s){
System.out.println(s.getClass().getName()+" Area:"+s.getArea());
}
public static void printPerimter(Shapes s){
System.out.println(s.getClass().getName()+" Perimter:"+s.getPerimter());
}
}
6. 自定义一个类,覆写equals方法,以满足自身业务需求
覆写equals()方法思路:
(1)判断要比较对象的是否为null,若是直接返回false,若不比较则可能会出现空指针异常(NullPointerException);
(2)判断是否在与自身比较(通过==比较地址),若是直接返回true;
(3)判断要比较的两个对象是否为同类,若是再进行接下来比较,若不是直接返回false。若不判断,则可能出现强转异常(classCastException);
(4)通过向下转型,比较两对象内容是否相等。
7. 举例说明运算符instanceof的使用场景。
a instanceof A:
其中a为对象,A为类
1.a为A的实例或者为A子类的示例,返回true
2.a为A父类的示例返回false
3.a与A没有任何关系,编译错误
class Animal{
public void getName(){}
public void getAge(){}
}
class Dog extends Animal{
private String name;
private int age;
Dog(String name,int age){
this.name=name;
this.age=age;
}
@Override
public void getName(){
System.out.println("Dog's name is:"+name);
}
@Override
public void getAge(){
System.out.println("Dog's name is:"+age);
}
}
class Person{}
public class test{
public static void main(String[] args){
Animal a=new Animal();
Dog d=new Dog("jack",5);
Person p=new Person();
System.out.println(d instanceof Animal);//true;
System.out.println(a instanceof Dog);//false;
// System.out.println(p instanceof A);编译错误 Incompatible conditional operand types Person and A
}
}
8. 谈谈抽象类与接口的异同以及两者的使用场景。
相同点:
两者都是抽象类, 都不能实例化.
继承两者的类或者接口, 都必须要实现已经声明的抽象方法.
不同点:
抽象类使用 extends , 接口使用 implements .
类只有单继承, 接口可以多个.
接口只能定义 public 方法,public final static 变量.
类可以有缺省或者默认方法,接口不行.
使用场景:
抽象类强调继承关系.
接口偏于功能的实现.