今天下午被一个问题搞昏了,颠覆了以前的观点,并总结了一些问题,提炼出了一些知识。
package four_5;
public abstract class Animal {
String name;
int age=10;
double weight;
abstract void move();
abstract void eat();
public void showInfo() {
System.out.println("动物的名字是:"+name+"|"+"动物的年龄是:"+age+"|"+"动物的体重为"+weight);;
}
}
class Bird extends Animal{
int age =20;
public Bird(String name, double weight) {
this.name = name;
this.weight = weight;
}
public void showInfo() {
System.out.println("小鸟的名字是:"+name+"|"+"小鸟的年龄是:"+age+"|"+"小鸟的体重为"+weight);;
}
@Override
public void move() {
System.out.println("鸟的运动方式飞");
}
public void eat() {
System.out.println("鸟喜欢吃虫");
}
}
class TestAnimal{
public static void main(String[] args) {
Animal a = new Bird("麻雀", 0.5);
a.move();
a.eat();
a.showInfo();
System.out.println(a.age);//这里的运行结果是10;
}
}
这里改变的只是上面的部分代码。
class Bird extends Animal{
int age;
public Bird(String name, double weight) {
this.name = name;
this.weight = weight;
}
这里运行结果还会是10。
package four_5;
public abstract class Animal {
String name;
int age=10;
double weight;
abstract void move();
abstract void eat();
public void showInfo() {
System.out.println("动物的名字是:"+name+"|"+"动物的年龄是:"+age+"|"+"动物的体重为"+weight);;
}
}
class Bird extends Animal{
int age;
public Bird(String name, int age,double weight) {
this.name = name;
this.age = age;
this.weight = weight;
}
public void showInfo() {
System.out.println("小鸟的名字是:"+name+"|"+"小鸟的年龄是:"+age+"|"+"小鸟的体重为"+weight);;
}
@Override
public void move() {
System.out.println("鸟的运动方式飞");
}
public void eat() {
System.out.println("鸟喜欢吃虫");
}
}
class TestAnimal{
public static void main(String[] args) {
Animal a = new Bird("麻雀",2, 0.5);
a.move();
a.eat();
a.showInfo();
System.out.println(a.age);//这里运行结果是2了。
}
}
首先我们将一下继承,继承是子类继承父类的非私有方法和属性,我这个问题就是受到了向上转型的困扰,我们都知道在多态运行机制中,父类引用指向子类对象,比如 Animal a = new Bird();那么a.age就会是调用的父类成员变量,因为子类不会覆盖父类的成员变量,动态方法机制对从成员变量没有影响。
但是比如第一个代码,用了一个构造函数,情况就不同了,它相当于改变了成员变量的值,感觉覆盖了父类成员变量的值,其实不应该这样理解,因为这个子类继承的父类的成员变量,如果父类有个变量age=10,子类再来个变量age=5,那么子类对象中就会有age=10,age=5都存在,
其实这里应该好好讲一下继承的概念;子类继承父类,在创建一个子类对象在内存中开辟一个空间的时候,里面有一部分空间是保存的父类的的内容那部分空间只有age=10,在父类引用指向子类的对象的时候只是指的是那部分空间的内容,所以 父类引用.age就会等于5。
你们可以画一画内存图来理解,注意理解开辟子类对象时父类的内容占的一部分空间就懂了。
还有一句话:在java核心技术卷一:super不能说一种引用,应该说是对父类内容使用的一个关键字。
在继承中,在调用方法的时候,遇到子类方法和父类方法重名的情况,子类中的方法会覆盖父类的同名方法。