Tham chiếu Java khác với con trỏ C như thế nào?


97

C có con trỏ và Java có cái được gọi là tài liệu tham khảo. Họ có một số điểm chung theo nghĩa là tất cả đều hướng đến một cái gì đó. Tôi biết rằng con trỏ trong C lưu trữ các địa chỉ mà chúng trỏ đến. Làm tài liệu tham khảo cũng lưu trữ địa chỉ? Làm thế nào chúng khác nhau ngoại trừ con trỏ linh hoạt hơn và dễ bị lỗi?


10
lưu ý C ++ cũng có các tham chiếu khác với các tham chiếu con trỏ hoặc java
jk.

@jk. Tôi nghĩ nó sẽ giống như trong Java. Sự khác biệt là gì?
Gnijuohz

17
Các tham chiếu C ++ không thể đảo ngược (nghĩa là bạn không thể thay đổi đối tượng được chỉ định) và không thể rỗng (nghĩa là bạn không thể tham chiếu chúng một cách hợp lệ không có đối tượng nào cả).
AProgrammer

@Gnijuohz Đọc lại những gì @AProgrammer đã nói: Một finaltham chiếu trong Java gần tương đương với một tham chiếu C ++. Lý do mà chúng không tương đương chính xác là, một tham chiếu C ++ cũng không phải là null, trong khi một finaltham chiếu trong Java là nullable.
Utku

Câu trả lời:


142

Tài liệu tham khảo có thể được thực hiện bằng cách lưu trữ địa chỉ. Thông thường các tham chiếu Java sẽ được triển khai như các con trỏ, nhưng điều đó không bắt buộc bởi đặc tả. Họ có thể đang sử dụng một lớp bổ sung bổ sung để cho phép thu gom rác dễ dàng hơn. Nhưng cuối cùng, nó sẽ (hầu như luôn luôn) sôi sục với các con trỏ (kiểu C) có liên quan đến việc thực hiện các tham chiếu (kiểu Java).

Bạn không thể làm số học con trỏ với các tài liệu tham khảo. Sự khác biệt quan trọng nhất giữa một con trỏ trong C và một tham chiếu trong Java là bạn thực sự không thể lấy (và thao tác) giá trị cơ bản của một tham chiếu trong Java. Nói cách khác: bạn không thể thực hiện số học con trỏ.

Trong C, bạn có thể thêm một cái gì đó vào một con trỏ (tức là địa chỉ) hoặc trừ thứ gì đó để trỏ đến những thứ "gần đó" hoặc trỏ đến các địa điểm ở bất kỳ nơi nào .

Trong Java, một tham chiếu chỉ đến một điều và chỉ điều đó. Bạn có thể làm cho một biến giữ một tham chiếu khác , nhưng bạn không thể yêu cầu nó chỉ ra "điều sau điều ban đầu".

Tài liệu tham khảo được đánh máy mạnh mẽ. Khác biệt nữa là các loại tài liệu tham khảo được nhiều kiểm soát chặt chẽ hơn trong Java so với loại một con trỏ trong C. Trong C bạn có thể có một int*và bỏ nó vào một char*và chỉ tái diễn dịch bộ nhớ tại địa điểm đó. Việc giải thích lại đó không hoạt động trong Java: bạn chỉ có thể diễn giải đối tượng ở đầu kia của tham chiếu như một cái gì đó đã có (tức là bạn chỉ có thể chuyển một Objecttham chiếu đến Stringtham chiếu nếu đối tượng được trỏ thực sự là a String).

Những khác biệt đó làm cho con trỏ C mạnh hơn, nhưng cũng nguy hiểm hơn. Cả hai khả năng đó (số học con trỏ và diễn giải lại các giá trị được trỏ đến) thêm tính linh hoạt cho C và là nguồn gốc của một số sức mạnh của ngôn ngữ. Nhưng chúng cũng là nguồn gây ra vấn đề lớn, bởi vì nếu sử dụng không đúng cách, chúng có thể dễ dàng phá vỡ các giả định rằng mã của bạn được xây dựng xung quanh. Và thật dễ dàng để sử dụng chúng không chính xác.


18
+1 cho có thể . Đừng dựa vào chi tiết thực hiện.
một CVn

2
+1 Bộ sưu tập rác không đáng được nhắc đến như một điểm in đậm cụ thể? Đó là một cách khác mà con trỏ C mạnh hơn nhưng cũng nguy hiểm hơn (nguy cơ con trỏ lơ lửng để giải phóng bộ nhớ gây ra hỏng bộ nhớ, nguy cơ rò rỉ bộ nhớ)
MarkJ

Một điểm khác biệt giữa các tham chiếu và các con trỏ là một con trỏ trong C có thể được chuyển đổi thành một chuỗi các số (ví dụ: bằng cách sử dụng memcpyđể di chuyển một thành một char[]) và ngược lại. Nếu một con trỏ được chuyển đổi thành một chuỗi các số được lưu trữ ở một nơi nào đó (có thể được hiển thị trên màn hình và được sao chép bởi người vận hành trên một tờ giấy), tất cả các bản sao của con trỏ trong máy tính sẽ bị hủy và chuỗi số đó được chuyển đổi trở lại một con trỏ (có lẽ sau khi được toán tử gõ vào), con trỏ vẫn phải trỏ đến cùng một thứ mà nó đã làm trước đó. Một chương trình mà ...
supercat

... đã hiển thị một con trỏ dưới dạng số và sau đó chuyển đổi các số được nhập thủ công thành một con trỏ, có thể là "ác", nhưng nó sẽ không gọi bất kỳ Hành vi không xác định nào trừ khi toán tử nhập vào các số chưa được hiển thị để tạo thành hợp lệ con trỏ. Do đó, việc thu gom rác đa năng là không thể trong C di động hoàn toàn, bởi vì không có cách nào máy tính có thể biết liệu một bản sao của một con trỏ có tồn tại ở đâu đó trong vũ trụ hay không.
supercat

Theo JLS, §4.3.1, các tham chiếu trong Java là các con trỏ, vì vậy "Thông thường các tham chiếu Java sẽ được triển khai như các con trỏ, nhưng điều đó không bắt buộc theo đặc tả." là sai.
Lew Bloch

8

Tài liệu tham khảo C ++ lại khác.

Chúng phải được khởi tạo và không thể rỗng (ít nhất là không phải trong một chương trình được hình thành tốt) và không thể được nối lại để đề cập đến một cái gì đó khác. một tham chiếu C ++ giống như một bí danh cho một đối tượng.

Một sự khác biệt quan trọng khác giữa các con trỏ và các tham chiếu Java / C ++ là bạn có thể lấy địa chỉ của một con trỏ mà bạn không thể truy cập vào địa chỉ của một tham chiếu (thực sự không cần phải có một tham chiếu C ++ như một đối tượng trong bộ nhớ) con trỏ tới một con trỏ nhưng không phải là một tham chiếu đến một tham chiếu


4

Tài liệu tham khảo Java và con trỏ C khác nhau ở hai điểm chính xác:

  1. Không có số học con trỏ cho trước đây.
  2. Và bạn không thể tạo tham chiếu Java cho bất cứ điều gì bạn muốn, bạn chỉ có thể sao chép những tham chiếu đã lưu ở đâu đó (trường tĩnh, trường đối tượng, biến cục bộ) hoặc được trả về bởi các lệnh gọi hàm (như lệnh gọi hàm tạo), do đó tất cả đều tham chiếu đến Java đối tượng (không bao giờ để loại cơ bản như tài liệu tham khảo, char, intvà vân vân).

Ai đó đã viết rằng Tài liệu tham khảo được gõ mạnh, bởi vì bạn không thể buộc trình biên dịch coi int*là một char*.
Hoàn toàn ngoài thực tế chuyển đổi cụ thể là thực sự an toàn , không có tính đa hình trong C, do đó so sánh là không bắt đầu.
Chắc chắn, Java được gõ mạnh hơn C, không phải là tính năng của con trỏ C so với tham chiếu Java, bạn cần sử dụng JNI để phá vỡ an toàn loại (ngoài việc bỏ qua các hạn chế chung), nhưng ngay cả trong C bạn cũng phải ép buộc trình biên dịch.

Có người viết rằng Java tài liệu tham khảo có thể được thực hiện như con trỏ C, mà tôi nói chắc chắn, vì họ là đúng ít mạnh mẽ, trên máy 32Bit họ thường là, nếu JVM được thực hiện trong C . Mặc dù trên các máy 64Bit, chúng thường được nén các con trỏ đối tượng thông thường ("OOPs nén") để tiết kiệm không gian và băng thông.
Dù sao, những con trỏ C đó cũng không cần tương đương với địa chỉ phần cứng, ngay cả khi chúng thường (> 99% triển khai) là vì lý do hiệu suất.
Cuối cùng, đó là một chi tiết triển khai không được đưa ra cho lập trình viên.


-1

Họ hơi khác nhau. Trong Java, một bản sao của tham chiếu được sao chép vào ngăn xếp của một hàm được gọi, trỏ đến cùng một đối tượng như hàm gọi và cho phép bạn thao tác với đối tượng đó. Tuy nhiên, bạn không thể thay đổi đối tượng mà chức năng gọi tham chiếu.

Hãy xem xét mã java sau đây

public static void changeRValue(StringBuffer sb){
    sb = new StringBuffer("helllllo"); /*attempt to assign the reference
                                        to a new object*/
}
public static void main(String[] args) {
    StringBuffer sb = new StringBuffer("hi");     //Create a new string buffer
    changeRValue(sb);                             //Call changeRValue
    System.out.println(sb.toString());            //Prints "hi" not "hello"
}

Bây giờ hãy xem xét một con trỏ trong c ++:

void func(Dog* dog){
    *dog = Dog("hello world"); //Change the value of dog to a new object
}

int main(int argc, const char * argv[]) {
    Dog dog1("hi");                            //Create a dog object
    func(&dog1);                               //pass the address of dog
    cout << dog1.name;                         //Prints "hello world" not hi.
    return 0;
}

Tôi nghĩ rằng tôi có thể thêm rằng nó có thể được xem là tương tự như một con chó const *
Eladian

2
Bạn có thể sửa đổi đối tượng trỏ tới trong Java một cách dễ dàng như trong C ++. Bạn chỉ cần có quyền truy cập vào các thành viên phù hợp. Các đối tượng Java không có toán tử gán vì Java không hỗ trợ quá tải toán tử do người dùng định nghĩa, do đó bạn không thể sử dụng toán tử quá tải. Việc thiếu Java không liên quan gì đến thực tế là các tham chiếu Java giống như các con trỏ C ++, thiếu sót của số học con trỏ.
Ded repeatator
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.