前两天学习了有关java面向对象的思想,其中需要了解代码在内存中的体现,学习后,就自己总结了一下,下边是一段程序:
import static java.lang.System.*;
class MemoryDemo
{
public static void main(String[] args)
{
/*语句1:*/
String name1 = "rcj";
/*
语句2:
String name2 = new String("rcj");
out.println(name1==name2);//false.
out.println(name1.equals(name2));//true
语句1与语句2的不同之处在于:
语句1只创建1个"rcj"对象,语句2会创建2个"rcj"对象。
在内存中name1与name2会指向两个不同的"rcj"对象,
但是由于其内容相同,equals会返回true.
*/
Student rcj = new Student(name1,23,"rcjHand");
rcj.move();
rcj.study();
out.println(rcj.getName());
}
}
class People
{
private String name;
private int age;
private static String hand;
People(String name,int age,String hand)
{
this.name = name;
this.age = age;
this.hand = hand;
}
public static void move()
{
out.println(/*People.*/hand+"....move");
//此处hand前省略的引用为People类名,即静态属性所属的类。
}
public String getName()
{
return /*this.*/name;
//此处name前省略的引用为this即调用的对象。
}
}
class Student extends People
{
Student(String name,int age,String hand)
{
super(name,age,hand);
}
public void study()
{
int days=0;
out.println("Study..."+days+"...day");
}
}
根据代码我画了如下一个图示:
内存分为了四部分,栈、堆、方法区(数据段、代码段)
栈:栈内存中存放的都为程序执行过程中的临时变量和程序,例如在程序执行过程中的变量(name1,rcj),都为临时的变量。在程序执行过程中,该部分内存在不断做入栈和出栈操作。
堆:在堆内存中一方面是存放实际的对象,如:新new出来的Student对象就是存放在该部分内存中;同时另一方面,在该内存中还有一个常量池,在常量池中存放一些基本数据类型的常量值等信息,例如给name1赋的字符串常量“rcj”就是存放在该部分内存中。
代码段:在该部分内存中存放的是一些非静态的方法代码。在堆内存中的对象实例,只包括对象的属性,例如在Student类中的变量days,而不包括对象的相关方法,其中的相关非静态方法就是放在该部分内存中,在实例的对象需要调用相关方法时,会将相关的引用加载到栈内存中执行相关代码。
数据段:该部分内存存放的是相关的静态方法和变量。静态的方法和变量是随着类的加载而加载的,也就是说被static修饰的相关成员在对象实例化前就已经初始化好了,那么就导致静态的方法只可以引用静态的成员,而不可以引用非静态的成员。
注意:
1、静态的方法只可以引用静态成员。
2、在代码中有关语句1和语句2的比较,语句1只创建1个"rcj"对象,语句2会创建2个"rcj"对象;由此可以说明"rcj"字符串对象在内存中如果不重新new,只有一个。
3、在数据段中不会出现有关this和super的引用,其相关引用一般是指向父类或本类和子类;而在代码段中的很多缺省引用为this和super。
总结:有关代码在内存中的体现,感觉应该好好理解一下,只有理解好其中的原理才可以在编写代码和设计过程中有全局和宏观的把控,但是感觉自己理解的还是很有限的,需要在以后的学习过程中多多体会和发现,最主要的是自己运用的还相当少,所以理解上肯定还会有很多问题,继续努力吧!