QUESTION:
1.使用debug跟踪子类对象实例化执行顺序:package lianxi;
//子类
public class abc extends ab{
int a=0,b=0,c=0;
abc(int x)
{
super(x); a=x+7;
}
abc(int x,int y){
super(x,y);a=x+5;b=y+5;
}
abc(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) {
abc p1=new abc(2,3,5);
abc p2=new abc(10,20);
abc p3=new abc(1);
System.out.println("a+b+c="+p1.add());
System.out.println("a+b="+p2.add());
System.out.println("a="+p3.add());
}
}
package lianxi;
//父类
public class ab {
private int x=0,y=0,z=0;
ab(int x){
this.x=x;
}
ab(int x,int y){
this(x);
this.y=y;
}
ab(int x, int y,int z){
this(x,y);
this.z=z;
}
public int add() {
return x+y+z;
}
}
现在对子类进行debug测试,验证子类对象实例化执行顺序。
1.abc p1=new abc(2,3,5);
2.abc p2=new abc(10,20);
3.abc p3=new abc(1);
语句1如下所示:
(1)
(2)
(3)
(4)
(5)
(6)
随后进行赋值。2,3语句debug顺序与其类似。
首先进入子类的构造函数,在赋值前进入父类构造函数中,然后由于重载的原因,不断跳跃到前一个构造函数中,最后进入最终父类object中,结束后进行赋值操作。
可以通过对象引用的方法,创建两个类,这两个类中都包含另一个类的成员。
package lianxi;
class A{
private abc b;
public void bb(abc b){
if(b!=null){
System.out.println("ooo");
this.b=b;
}
}
public abc get(){
if(b!=null){
return b;
}
else
return null;
}
}
class abc{
private A a;
public abc(A a){
this.a=a;
a.bb(this);
}
public static void main(String[] args) {
A a=new A();
abc bb = new abc(a);
}
}
输出:
区别:组合现象是一个类的对象引用是另一个类的属性,对象引用可以指向其对应类的任何一个对象,但对象只能调用其规定好的方法,无法修改;继承是子类将父类的属性和方法全部继承下来,子类可以重载和覆盖父类的方法,继承具有类似一对一的属性。
宜用组合的场景:一个类的对象与另一个类的对象具有一对多关系,一个类的方法对于另一个类来说永远不用改变。
宜用继承的场景:两个类的对象具有一对一的关系,一个类需要重载或覆盖另一个类的方法;抽象类等等。
4.java运行时多态的含义与作用:运行时多态:当同一个引用变量指向不同的子类实例,然后访问引用变量成员方法, 方法会有不同的表现。使用父类引用指向子类对象,再调用某一父类中的方法时,不同子类会表现出不同结果。
作用:运行时多态性提供了更大的灵活性,所有事情都在运行时得到解决。
package lianxi;
abstract public class Shapes {
protected int x,y,k;
protected double m;
public Shapes(int x,int y,int k,double m) {
this.x=x;
this.y=y;
this.k=k;
this.m=m;
}
abstract public double getArea();
abstract public double getPerimeter();
}
package lianxi;
import java.awt.*;
public class Rect extends Shapes{
public double getArea() {
return k*m;
}
public double getPerimeter() {
return (2*k+2*m);
}
public Rect(int x,int y,int width,int height) {
super(x,y,width,height);
}
}
package lianxi;
import java.awt.*;
public class Triangle extends Shapes{
public Triangle(int baseA,int baseB,int baseC) {
super(baseA,baseB,baseC,0);
m=(baseA+baseB+baseC)/2.0;
}
public double getArea() {
return(Math.sqrt(m*(m-k)*(m-x)*(m-y)));
}
public double getPerimeter() {
return (x+y+k);
}
}
package lianxi;
import java.awt.*;
public class Circle extends Shapes{
public Circle(int x,int y,int width) {
super(x,y,width,width/2.0);
}
public double getArea() {
return m*m*Math.PI;
}
public double getPerimeter() {
return 2*Math.PI*m;
}
}
package lianxi;
import java.awt.*;
import java.applet.*;
public class RunShape extends Applet {
Rect rect=new Rect(5,15,25,25);
Triangle tri =new Triangle(5,5,8);
Circle cir=new Circle(13,90,25);
private void drawArea(Graphics g,Shapes s,int a,int b) {
g.drawString(s.getClass().getName()+" Area"+s.getArea(),a,b);
}
private void drawPerimeter(Graphics g,Shapes s,int a,int b) {
g.drawString(s.getClass().getName()+"Perimeter"+s.getPerimeter(),a,b);
}
public void paint(Graphics g) {
g.drawRect(rect.x, rect.y, rect.k, (int)rect.m);
drawArea(g,rect,50,35);
drawPerimeter(g,rect,50,55);
drawArea(g,tri,50,75);
drawPerimeter(g,tri,50,95);
g.drawOval(cir.x-(int)cir.k/2,cir.y-(int)cir.k/2,cir.k,cir.k);
drawArea(g,cir,50,115);
drawPerimeter(g,cir,50,135);
}
}
5.使用接口改写6.8:
public interface Shapes {
public abstract double getArea();
public abstract double getPerimeter();
}
public class Rect implements Shapes{
int x,y;
double width,height;
public Rect(int x,int y,double width,double height) {
this.x=x;
this.y=y;
this.width=width;
this.height=height;
}
public double getArea() {
return width*height;
}
public double getPerimeter() {
return 2*(width+height);
}
}
public class Triangle implements Shapes {
int baseA,baseB,baseC;
double m;
public Triangle(int x,int y,int z) {
baseA=x;
baseB=y;
baseC=z;
m=(baseA+baseB+baseC)/2.0;
}
public double getArea() {
return (Math.sqrt(m*(m-baseA)*(m-baseB)*(m-baseC)));
}
public double getPerimeter() {
return (double)(baseA+baseB+baseC);
}
}
public class Circle implements Shapes{
int x,y;
double d,r;
public Circle(int x,int y,int width) {
this.x=x;
this.y=y;
r=width/2.0;
d=(double)width;
}
public double getArea() {
return (r*r*Math.PI);
}
public double getPerimeter() {
return (d*Math.PI);
}
}
import java.applet.*;
import java.awt.*;
public class RunShape extends Applet {
Rect rect=new Rect(5,15,25,25);
Triangle tri=new Triangle(5,5,8);
Circle cir=new Circle(13,90,25);
private void drawArea(Graphics g,Shapes s,int a,int b) {
g.drawString(s.getClass().getName()+"Area"+s.getArea(), a,b);
}
private void drawPerimeter(Graphics g,Shapes s,int a,int b) {
g.drawString(s.getClass().getName()+"Perimeter"+s.getPerimeter(),a,b);
}
public void paint(Graphics g) {
g.drawRect(rect.x, rect.y,(int)rect.width, (int)rect.height);
drawArea(g,rect, 50, 35);
drawPerimeter(g,rect,50,55);
drawArea(g,tri,50,75);
drawPerimeter(g,tri,50,95);
g.drawOval(cir.x-(int)cir.r,cir.y-(int)cir.r ,(int)cir.d,(int)cir.d);
drawArea(g,cir,50,115);
drawPerimeter(g,cir,50,135);
}
}
6.自定义类,覆写equals:
class Man{
private String name;
private int age;
Man(String name,int age){
this.name=name;
this.age=age;
}
public String toString(){
return this.name+"今年"+this.age+"岁";
}
public boolean equals(Object obj){//Object类可接受任何类
if(obj==null){//判断是否为空,若不判断则会出先空指针异常(NullPointerException)
return false;
}
if(this==obj){//判断是否在与自身比较(通过比较地址),若是则直接返回true
return true;
}
if(!(obj instanceof Man)){//instanceof作用为判断其左边对象是否为右边对象的实例,此处为判断主方法中equals()方法括号中的对象是否为Person类
return false;
}
//到达此处时必定是同类但不同地址的对象在比较
Man per=(Man)obj;//向下转型,比较属性值
return this.name.equals(per.name)&&this.age==per.age;//判定属性内容是否相等(易错点)
}
}
class Student{}
public class Test{
public static void main(String[] args) {
Person per1=new Man("张三",18);
Person per2=new Man("张三",18);
Person per3=new Man("lisi",19);
Person per4=null;
Student stu=new Student();
System.out.println(per1.equals(per1));//true
System.out.println(per1.equals(stu));//false
System.out.println(per1.equals(per3));//false
System.out.println(per1.equals(per4));//false
}
}
7.instanceof使用场景:
用来判断两类是否存在父类与子类的关系。
举个栗子:
a为对象引用,A为类。a为A实例或A子类实例,返回true。
a为A父类实例,返回false。
a和A无关系,编译不通过。
相同点:
两者都是抽象类,都不能实例化。
interface实现类及abstract class的子类都必须要实现已经声明的抽象方法。



