前兩天學習了有關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。
總結:有關代碼在內存中的體現,感覺應該好好理解一下,只有理解好其中的原理纔可以在編寫代碼和設計過程中有全局和宏觀的把控,但是感覺自己理解的還是很有限的,需要在以後的學習過程中多多體會和發現,最主要的是自己運用的還相當少,所以理解上肯定還會有很多問題,繼續努力吧!