1. 程式人生 > >棧記憶體與堆記憶體在資料共享方面的區別

棧記憶體與堆記憶體在資料共享方面的區別

D.false true
對於這道題,考察的是對String型別的認識以及編譯器優化。JavaString不是基本型別,但是有些時候和基本型別差不多,如String    b =    "tao"   可以對變數直接賦值,而不用 new 一個物件(當然也可以用 new)。所以String這個型別值得好好研究下。 

Java中的變數和基本型別的值存放於棧記憶體,而new出來的物件本身存放於堆記憶體,指向物件的引用還是存放在棧記憶體。例如如下的程式碼:

int  i=1;

    String s =  new  String( "Hello World" );

變數is以及1

存放在棧記憶體,而s指向的物件”Hello World”存放於堆記憶體。

  MESSAGE 成員變數及其指向的字串常量肯定都是在棧記憶體裡的,變數 a 運算完也是指向一個字串“ taobao ”啊?是不是同一個呢?這涉及到編譯器優化問題。對於字串常量的相加,在編譯時直接將字串合併,而不是等到執行時再合併。也就是說

String a =  "tao" + "bao" ;String a =  "taobao" ;編譯出的位元組碼是一樣的。所以等到執行時,根據上面說的棧記憶體是資料共享原則,aMESSAGE

指向的是同一個字串。而對於後面的(b+c)又是什麼情況呢?b+c只能等到執行時才能判定是什麼字串,編譯器不會優化,想想這也是有道理的,編譯器怕你對b的值改變,所以編譯器不會優化。執行時b+c計算出來的"taobao"和棧記憶體裡已經有的"taobao"是一個嗎?不是。b+c計算出來的"taobao"應該是放在堆記憶體中的String物件。這可以通過System. out .println( (b+c)== MESSAGE );的結果為false來證明這一點。如果計算出來的b+c也是在棧記憶體,那結果應該是trueJavaString的相加是通過StringBuffer實現的,先構造一個StringBuffer
裡面存放”tao”,然後呼叫append()方法追加”bao”,然後將值為”taobao”StringBuffer轉化成String物件。StringBuffer物件在堆記憶體中,那轉換成的String物件理所應當的也是在堆記憶體中。下面改造一下這個語句System. out .println( (b+c).intern()== MESSAGE );結果是true intern() 方法會先檢查 String ( 或者說成棧記憶體 ) 中是否存在相同的字串常量,如果有就返回。所以 intern()返回的就是MESSAGE指向的"taobao"。再把變數bc的定義改一下,

final  String b =  "tao" ;

final  String c =  "bao" ;

       System. out .println( (b+c)== MESSAGE );

現在bc不可能再次賦值了,所以編譯器將b+c編譯成了”taobao”。因此,這時的結果是true

在字串相加中,只要有一個是非final型別的變數,編譯器就不會優化,因為這樣的變數可能發生改變,所以編譯器不可能將這樣的變數替換成常量。例如將變數bfinal去掉,結果又變成了false。這也就意味著會用到StringBuffer物件,計算的結果在堆記憶體中。

如果對指向堆記憶體中的物件的String變數呼叫intern()會怎麼樣呢?實際上這個問題已經說過了,(b+c).intern()b+c的結果就是在堆記憶體中。對於指向棧記憶體中字串常量的變數呼叫intern()返回的還是它自己,沒有多大意義。它會根據堆記憶體中物件的值,去查詢String池中是否有相同的字串,如果有就將變數指向這個string池中的變數。

String a = "tao"+"bao";

       String b = new String("taobao");

      System.out.println(a==MESSAGE); //true

      System.out.println(b==MESSAGE);  //false

      b = b.intern();

      System.out.println(b==MESSAGE); //true

System. out .println(a==a.intern());  //true

相關推薦

記憶體記憶體資料共享方面區別

D.false true對於這道題,考察的是對String型別的認識以及編譯器優化。Java中String不是基本型別,但是有些時候和基本型別差不多,如String b =  "tao" ; 可以對變數直接賦值,而不用 new 一個物件(當然也可以用 new)。所以String這個型別值得好好研

簡述資料結構:記憶體記憶體的儲存方式 js中的原始值

在討論堆疊前,先要明確什麼是原始值、引用值。 1.變數可以存放兩種型別的值: 原始值 和 引用值 2.原始值代表原始資料型別的值,也叫基本資料型別,包括 Number、Stirng、Boolean、Null、Underfined。 3.引用值指的是複合資料型別的

JavaScript 資料結構演算法之美 - 記憶體記憶體 、淺拷貝深拷貝

前言 想寫好前端,先練好內功。 棧記憶體與堆記憶體 、淺拷貝與深拷貝,可以說是前端程式設計師的內功,要知其然,知其所以然。 筆者寫的 JavaScript 資料結構與演算法之美 系列用的語言是 JavaScript ,旨在入門資料結構與演算法和方便以後複習。 棧 定義 後進者先出,先進者後出,簡

【黑馬程式設計師】記憶體記憶體

java中記憶體分配策略及堆和棧的比較    1 記憶體分配策略    按照編譯原理的觀點,程式執行時的記憶體分配有三種策略,分別是靜態的,棧式的,和堆式的.    靜態儲存分配是指在編譯時就能確定每個資料目標在執行時刻的儲存空間需求,因而在編譯時就可以給他們分配固定的記憶體空間.這種分配策略要求程式程式碼中

Java學習之記憶體記憶體

堆:(物件) 引用型別的變數,其記憶體分配在堆上或者常量池(字串常量、基本資料型別常量),需要通過new等方式來建立。 堆記憶體主要作用是存放執行時建立(new)的物件。 (主要用於存放物件,存取速度慢,可以執行時動態分配記憶體,生存期不需要提前確定)

javascript:記憶體記憶體淺談

首先,我們來舉個爪子: var m = 1; var n = m; n=2; console.log(m); 大家覺得答案是什麼?是一的情自覺點贊,不開玩笑了,其實這個很簡單,對吧。那麼我們再來一

Java直接記憶體記憶體

NIO的Buffer提供了一個可以不經過JVM記憶體直接訪問系統實體記憶體的類——DirectBuffer。 DirectBuffer類繼承自ByteBuffer,但和普通的ByteBuffer不同,普通的ByteBuffer仍在JVM堆上分配記憶體,其最大記憶體受到最大堆記憶體的限制;而Direc

js記憶體記憶體垃圾回收機制

v8作為javascirpt引擎,對變數的儲存主要有兩種位置:棧儲存和堆儲存 棧記憶體儲存基本型別的變數:如Number,String,boolen,undefined,null,以及對物件和陣列變數的指標,物件是動態分配記憶體,陣列的初始化方式分為: 動態初始化:初始化

記憶體對外記憶體區別

名詞解釋:     堆內記憶體:on-heap memory     對外記憶體:off-heap memory 堆內與堆外的關係      其實堆內堆外是兩個相對的關係,堆內記憶體是我們常用到的。Java分

C++學習--------------記憶體記憶體區別

資料結構中的堆與棧: 棧:是一種連續儲存的資料結構,具有先進後出的性質。通常的操作有入棧(圧棧)、出棧和棧頂元素。想要讀取棧中的某個元素,就要將其之前的所有元素出棧才能完成。類比現實中的箱子一樣。 堆:是一種非連續的樹形儲存資料結構,每個節點有一個值,整棵樹是經過排序的。特點是根結

智慧指標記憶體管理

  目錄 shared_ptr std::weak_ptr std::unique_ptr 使用時注意事項: ①.new的普通指標與shared_ptr轉換: ②.指向棧的指標與shared_ptr轉換: 3.智慧指標向常規指標的轉換 自從c++

記憶體記憶體區別(一個筆試題的一部分)

筆試題目:請解釋一個棧記憶體與一個堆記憶體的區別,請分析下面程式碼執行是否有問題,如果有問題請改正。 char* GetMemory(void) {      char p[] = "Hello world";      return p; } void main(void

java 記憶體 記憶體的涵義及使用範圍

class FunctionDemo {     /*陣列記憶體空間的區域劃分\     1、暫存器     2、本地方法區     3、方法區     4、棧記憶體         //棧記憶體的涵義:         1、儲存的區域性變數  ----區域性變數對應的

js記憶體記憶體區別

首先JavaScript中的變數分為基本型別和引用型別。基本型別就是儲存在棧記憶體中的簡單資料段,而引用型別指的是那些儲存在堆記憶體中的物件。 1、基本型別 基本型別有Undefined、Null、Boolean、Number 和String。這些型別在記憶體中分

js中的記憶體記憶體

1.簡介棧和堆 棧:棧會自動分配記憶體空間,實體記憶體是連續的,存放基本型別,簡單的資料段,        佔據固定大小的空間。            基本型別:String,Number,Boo

為什麼要有記憶體記憶體之分

 在看jvm原理的時候,經常會聽到堆疊,但對其概念默默糊糊,只知道棧是先進後出的資料結構(FILO),而堆是樹的一種特例。堆的特點是子節點都比父節點要小,堆用於動態建立分配記憶體,建立和刪除節點的時間

JavaScript記憶體記憶體區別

和棧這兩個字我們已經接觸多很多次,那麼具體是什麼存在棧中什麼存在堆中呢?就拿JavaScript中的變數來說: 首先JavaScript中的變數分為基本型別和引用型別。

Java中記憶體記憶體、方法區——淺析

  java中記憶體分配策略及堆和棧的比較  1 記憶體分配策略   按照編譯原理的觀點,程式執行時的記憶體分配有三種策略,分別是靜態的,棧式的,和堆式的. 靜態儲存分配是指在編譯時就能確定每個資料目標在執行時刻的儲存空間需求,因而在編譯時就可以給他們分配固定的記憶體空間.這種分配策略要求程式程式碼中不允許有

【Big Data 每日一題20181111】為什麼有記憶體記憶體之分

為什麼有棧記憶體和堆記憶體之分?         陣列引用變數只是一個引用,這個引用變數可以指向任何有效的記憶體,只有當該引用指向有效記憶體,才可以通過該陣列變數來訪問陣列。        實際的陣列物件被儲存在堆(heap)記憶體中;如果引用該陣列物件引用變數是一個區域

【Python】記憶體檢視(操作資料共享記憶體

memoryview memoryview可以使用不同的方式讀取和操作同一塊記憶體,並且原有的記憶體位元組不會隨意移動。類似於C中的強轉。 例如,使用memoryview修改一個短整型有符號整數陣列