Java小实例内存分析
本来是今天上午写这篇的,硬生生被我拖延到了下午。看了两天马士兵老师的Java教程,学到了一些Java内存机制。就自己写了一个小程序来分析一下。
废话不多说了,直接上代码吧。
interface PetCarer {
void feeds(Pet p, String food);
}
class Pet {
String name;
Pet(String name) {
this.name = name;
}
public String toString() {
return "Pet";
}
String eat(String food) {
return this + " " + this.name + " eats " + food + ".";
}
}
class Dog extends Pet {
String furColor;
Dog(String name, String furColor) {
super(name);
this.furColor = furColor;
}
public String toString() {
return "Dog";
}
String eat(String food) {
return this.furColor + " fur " + this + " " + this.name + " eats " + food + ".";
}
}
class Cat extends Pet {
String eyesColor;
Cat(String name, String eyesColor) {
super(name);
this.eyesColor = eyesColor;
}
public String toString() {
return "Cat";
}
String eat(String food) {
return this.eyesColor + " eyes " + this + " " + this.name + " eats " + food + ".";
}
}
class People {
String name;
int age;
People(String name, int age) {
this.name = name;
this.age = age;
}
public String toString() {
return "People " + this.name + "'s ";
}
public void feeds(Pet p, String food) {
System.out.println(this + p.eat(food));
}
}
class Worker extends People implements PetCarer {
String workType;
Worker(String name, int age, String workType) {
super(name, age);
this.workType = workType;
}
public String toString() {
return "Worker " + this.name + "'s ";
}
public void feeds(Pet p, String food) {
System.out.println(this + p.eat(food));
}
}
class Farmer extends People implements PetCarer {
String growType;
Farmer(String name, int age, String growType) {
super(name, age);
this.growType = growType;
}
public String toString() {
return "Famer " + this.name + "'s ";
}
public void feeds(Pet p, String food) {
System.out.println(this + p.eat(food));
}
}
public class Test {
public static void main(String[] args) {
int age = 21;
Pet pet = new Pet("mimi");
Dog dog = new Dog("dahuang", "yellow");
Cat cat = new Cat("jiafei", "blue");
People people = new People("egoistk", age);
Worker worker = new Worker("ZhangSan", 20, "banzhuan");
Farmer farmer = new Farmer("LiSi", worker.age, "rice");
people.feeds(pet, "hotdog");
pet = new Dog("dahuang", "yellow");
people.feeds(pet, "hotdog");
farmer.feeds(cat, "maoliang");
people = new Worker("egoistk", 21, "banzhuan");
people.feeds(pet, "hotdog");
}
}
首先来说一下Java里内存的四个部分分别放的是什么
内存区域 | 存放内容 |
---|---|
code segment | 代码段 |
data segment | 放静态数据常量 |
heap | 放创建出来的对象 |
stack | 放临时变量 |
然后我们来一步步分析main线程里面的语行执行时,内存里面发生了什么。
第一行 int age = 21; 在stack里创建了一个值为21的int类数据。
第二行 Pet pet = new Pet(“mimi”); 在stack里创建了一个Pet类的pet引用指向heap里一块由Pet类的构造方法拿到的一块内存。
然后Pet构造方法开始执行
传入的形参“mimi”首先在data segment里,然后被pet的name成员变量引用
第三行 Dog dog = new Dog(“dahuang”, “yellow”); Dog类继承于Pet类,heap里的Dog块内存里包含了一块Pet内存,调用Dog构造方法时先调用Pet构造方法
同理,第四行 Cat cat = new Cat(“jiafei”, “blue”); 执行之后内存里的情况如下
第五行 People people = new People(“egoistk”, age); people的age属性是从形参age复制的,而形参age就是局部变量age
People构造方法执行完后,形参age消失
第六行 Worker worker = new Worker(“ZhangSan”, 20, “banzhuan”); 和第七行 Farmer farmer = new Farmer(“LiSi”, worker.age, “rice”);同上理
然后就开始方法的调用,这里最主要讲讲多态的情况。
首先要出现多态就要满足三点条件:
1、有类的继承或者接口的实现
2、方法的重写
3、父类引用指向子类对象
比如
第八行 people.feeds(pet, “hotdog”); 的输出是
People egoistk’s Pet mimi eats hotdog.
第九行 pet = new Dog(“dahuang”, “yellow”); 出现了父类引用pet指向Dog子类对象
然后 第十行再次调用 people.feeds(pet, “hotdog”); 时,就出现了多态,输出为
People egoistk’s yellow fur Dog dahuang eats hotdog.
这里可以用下图解释
注意上图中红色的箭头,根据pet引用指向的Dog类型的对象实际上是指向了Dog中的Pet类型的对象,所以此时pet.furColor是无法访问的,但是调用pet.toString则调用的是Dog类的toString,因为重写的toString方法覆盖了从父类Pet中继承的toString方法。
如果想要访问pet.furColor那么要将pet强制转换,
Dog p = (Dog) pet;
System.out.println(pet.furColor);
如下图,强制转换后的p指向的是Dog类型对象