Khai báo vùng nhớ trong Java

Mình có thắc mắc là nếu khai báo theo new thì sẽ tạo 1 biến tham chiếu vùng nhớ vậy thì nó như con trỏ chứa địa chỉ để trỏ đến vùng nhớ trong C , AH nếu không phải thì việc khai báo string a = “abc” thì có phải gắn luôn a chung với vùng nhớ của nó ah @@

Nếu không khai báo new, khi gán string a = “abc” thì máy sẽ tìm xem có string nào trong pool là “abc” không, nếu có thì trỏ vào, nếu không thì tạo mới rồi trỏ vào.

2 Likes

mình đọc xong câu hỏi của bạn ko hiểu bạn đang hỏi gì luôn ý

trong 1 topic trước mình cũng hỏi về vấn đề biến trong java thì có bạn đã nói là trong java thì các biến đều là tham chiếu ( kể cả biến kiểu nguyên thủy ) , nên khi gán giá trị cho 1 biến thực chất là gán tham chiếu đến vùng nhớ , nếu dự liệu được tạo trên pool thì biến sẽ trỏ đến vùng nhớ trên pool , nếu dự liệu được tạo theo contructor thì sẽ dựa vào nội dung của constructor ( thường sẽ tạo dự liệu trên heap ) constructor sẽ trả về địa chỉ của vùng nhớ …

làm gì có, các kiểu nguyên thủy ko phải là tham chiếu/con trỏ mà là dữ liệu thật. Mấy class như Integer, Double mới là con trỏ tới dữ liệu thật trên heap, còn int, double là dữ liệu thật trên stack hết.

5 Likes

thanks moi nguoi nhieu

~.~

https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html

There are two kinds of types in the Java programming language: primitive types (§4.2) and reference types (§4.3). There are, correspondingly, two kinds of data values that can be stored in variables, passed as arguments, returned by methods, and operated on: primitive values (§4.2) and reference values (§4.3).

2 kiểu này khác nhau, kiểu nguyên thủy ko phải là kiểu reference.

Primitive values do not share state with other primitive values

“do not share state” nghĩa là kiểu nguyên thủy chứa giá trị thật, ko có vụ 2 biến nguyên thủy khác nhau cùng trỏ tới 1 giá trị như kiểu reference.

nếu kiểu nguyên thủy trong Java cũng là “tham chiếu” thì tốc độ nó chắc ngang ngửa Python (chậm hơn C 30-50 lần) chứ ko phải xấp xỉ C++ đâu

2 Likes

vậy cho mình hỏi trong ví dụ này :
int x = “abc”;
int y = “abc”;

nếu x và y như bạn nói nó lưu giá trị ngay tại vùng nhớ của biến là sai vì string abc được lưu trên string pool và 2 biến x,y chỉ tham chiếu đến string pool này nên khi so sánh a==b thì kết quả trả về là true

hoặc :
int x = new Integer(12);
Object obj = x ;
int y = (int) obj ;

Câu phản biện của bạn đã sai rồi thì sao mà phản biện được hả bạn.
int là kiểu nguyên thủy lưu giá trị tại biến, String là object nên trỏ đến 1 vùng nhớ khác.
Theo bạn cái biểu thức int x = "abc"; của bạn có hợp lệ không khi mà bạn mix kiểu nguyên thủy int với string => lỗi cú pháp. Nếu bạn chưa rõ kiểu primitive gồm những loại nào thì có thể xem link mà @tntxtnt gửi
Integer là kiểu object của int, việc chuyển hay ép kiểu qua lại giữa int và Integer ở 3 biểu thức cuối của bạn thực ra không phải là ép kiểu mà là boxing và unboxing, cú pháp thì nhìn giống như ép kiểu nhưng thực tế khi compile thì compiler sẽ thêm 1 vài đoạn code đặc biệt để chuyển từ int thành Integer và ngược lại.
Bạn nên tìm hiểu sâu hơn về java trước khi phản biện vì 2 câu phản biện của bạn đều sai cơ bản

1 Like

vậy cho mình hỏi :

public void swap (int x){

}

int y = 1 ;
swap(1);

ở đây bạn nói x và y là 2 biến riêng biệt và dữ liệu lưu trực tiếp tại biến ( giống C ) , hay x và y là 2 biến và cùng trỏ đến 1 vùng nhớ Integer pool chứa giá trị 1 ??

Phép so sánh == với java có 2 ý nghĩa, với kiểu dữ liệu nguyên thủy thì sẽ là so sánh giá trị, không phải so sánh ref, nên x == y ra true không có nghĩa là chúng cùng ref vào một vùng nhớ trên stack hay đâu đó. Lí do là vì các kiểu dữ liệu nguyên thủy thì không có method nên không tồn tại method equal đâu
Ví dụ: int x = 1; bạn không thể dùng dot syntax để gọi hành động từ x được

2 Likes

Nó chẳng trỏ đi đâu cả, biến kiểu nguyên thủy lưu và truyền giá trị ra vào method bằng cách copy giá trị của chính nó. Và nói luôn là trong java không có biến reference đâu. Nên biến kiểu object khi gán sẽ là copy giá trị “con trỏ” hay còn gọi là copy địa chỉ trên stack cho biến được gán. Nên tất cả biến trong java đều độc lập nhau, thấy đổi ở biến này sẽ không ảnh hưởng đến biến khác. Với object khi thấy đổi thuộc tính thì thấy có sự thay đổi thuộc tính đó ở biến khác là vì nó cùng chỉ vào 1 vùng nhớ trên stack thôi. Bản chất vẫn là độc lập khi thấy đổi lẫn nhau được

ý bạn là sẽ tạo ra 2 biến riêng biệt x và y sau đó sẽ copy value của y vào x …:smiley:

Yes. Mọi thứ bạn truyền, gán trong java đều là copy của chính biến đó bằng cách này hoặc cách khác

1 . khi khai báo

int x = 1 ;
Integer y = 1 ;
Integer z = x;

thì theo bạn biến y sẽ tham chiếu đến vùng nhớ Integer pool chứa giá trị 1 đúng không
còn x sẽ lưu trực tiếp giá trị 1 vào value của biến , vậy giả sử địa chỉ của biến x là xxx và địa chỉ của vùng nhớ mà y tham chiếu đến là yyy
vậy biến z lúc này tham chiếu đến địa chỉ của biến x là xxx

vậy ta thực hiện phép ==

y==z?true:false //true

??? rõ ràng địa chỉ khác nhau mà lại trả về true…

chú thay giá trị 1= 500, rồi xem kết quả lại, và hãy tự hỏi lại tại sao -.-

giá trị nằm trong khoảng -127 > 127 thì trả về true ngoài khoản đó trả về false

vậy ý anh có phải là đối với phép gán Integer z = x; thì thực chất nó sẽ tạo 1 vùng nhớ mới với giá trị là 500 và vùng nhớ này không có liên quan gì đến biến x đúng ko ??

vì em đọc theo bài này : https://kipalog.com/posts/Pass-by-reference-va-pass-by-value
trong này có đoạn lấy ví dụ trong js thấy có cái ví dụ nó truyền 1 biến kiểu nguyên thủy mà vẫn truyền địa chỉ vào hàm , xong xuống dưới chỗ java nói giải thích như trên nên em cứ nghĩ là giống nhau

Như mình đã nói khi bạn đổi int thành Integer thì đây là phép boxing, compiler sẽ tự thêm 1 số code để thực hiện boxing int thành Integer. z chẳng tham chiếu đến địa chỉ của x, mà sẽ tham chiếu đến 1 instance Integer có giá trị int bằng với x sau khi auto boxing. Với một số jvm thì sẽ có Integer pool đối với các số nhỏ nên khi autoboxing với các số này thì thay vì tạo mới 1 object Integer thì nó lấy từ pool ra nên toán tử so sánh == sẽ ra được 2 instance cùng địa chỉ. Hình như bạn vẫn không thông biến primitive và biến object nhỉ.

1 Like

tên viết bài lười giải thích nên dòng “Java giải thích hoàn toàn giống javascript” viết sai chứ sao nữa, int trong Java ko phải là object như trong JS. Integer mới là object.

  • với các object có kích cỡ nhỏ, như Integer, Double, Character, …, mỗi lần tạo object mới phải cấp phát động, rất chậm so với xài thẳng giá trị thật nên Java mới cho xài thẳng kiểu nguyên thủy int, double, char.
  • sở dĩ phải có object “bọc” quanh (boxing) các kiểu nguyên thủy là vì Java chỉ viết có 1 kiểu duy nhất là OOP, nếu muốn tạo 1 hash map mà key là kiểu nguyên thủy thì ko có cách nào gọi key.hashCode() để lấy hash code của key vì các kiểu nguyên thủy ko phải là object, ko có phương thức hashCode() tương ứng. Java phải tạo các class Integer, Double, … thừa kế từ Object để có thể thừa kế phương thức hashCode().
  • vì object trong Java đều được cấp phát động, các kiểu boxing “nguyên thủy” này mà xài nhiều lần thì mỗi lần tạo biến mới đều phải cấp phát động, nên nếu buộc phải xài thì rất chậm. Người ta lại đẻ ra 1 chiêu mới tránh cấp phát động là đi lưu (cache) các giá trị thường sử dụng của các kiểu boxing “nguyên thủy”, để tránh cấp phát động. Với Integer thì các giá trị được cache là từ -128 tới 127, nên Integer a = 100Integer b = 100 đều trỏ tới object 100 trong cache, nên so sánh a == b trả về true. Còn Integer c = 200Integer d = 200 thì do 200 ko được cache nên d sẽ trỏ tới 1 object 200 khác với object 200 mà c trỏ tới, nên c == d trả về false.
6 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?