Nếu IDE của tôi rất thông minh, tại sao tôi cần phải đúc bản sao clone ()?


13

Kiểu IDE của tôi ( NetBeans ) kiểm traCollections trong khi tôi đang nhập mã. Nhưng sau đó, tại sao tôi phải bỏ vật bị trả về Object.clone()? Cái nào cũng được. Không có hại không hôi. Nhưng tôi vẫn không hiểu.

Là kiểm tra loại, mà không đúc, đối tượng trả lại Object.clone()không thể? Khung tổng quát khiến tôi nghĩ rằng IDE có thể kiểm tra loại tham chiếu đối tượng ở phía bên phải của dấu " = " mà không cần truyền trong khi tôi đang gõ? Tôi không hiểu

phụ lục
Trường hợp sử dụng của tôi chỉ là tôi có một Calendarlĩnh vực riêng , pubdate . Tôi sẽ viết:

Calendar getPubdate() {
    return pubdate;
}

nhưng có một rủi ro là kẻ xâm lược có thể sửa đổi tuổi dậy thì của tôi , vì vậy tôi đã trả lại một bản sao:

Calendar getPubdate() {
    return (Calendar) pubdate.clone();
}

Sau đó, tôi tự hỏi tại sao tôi cần phải đúc pubdate.clone(). Chữ ký phương thức có loại ngay tại đó. NetBeans sẽ có thể tìm ra cái đó. Và NetBeans dường như đang làm điều gì đó tương tự Collections.


5
Một ví dụ mã ngắn (!) Sẽ hữu ích.
Doc Brown

78
IDE tách biệt với chính ngôn ngữ, vì vậy Netbeans thông minh như thế nào không ảnh hưởng đến cách ngôn ngữ Java hoạt động.
JacquesB

7
Lưu ý, do kiểu trả về hiệp phương sai, nó được khuyến khích để trở lại MyObjecttừ clone()hơn Object- điều này loại bỏ toàn bộ vấn đề này. Chúng tôi khuyên bạn không bao giờ nên sử dụng clone()(Mục Java hiệu quả số 11).
Boris the Spider

Là sự nhấn mạnh câu hỏi của bạn về I hoặc trên 'cast "clone ()"' ? Bởi vì câu hỏi kết quả từ cái trước thực sự có thể là một câu hỏi tốt hơn nhiều so với câu hỏi sau.
dùng541686

Khi tôi đọc tiêu đề câu hỏi, điều duy nhất tôi nghĩ đến là this.clone()về đối tượng lập trình viên, đặc biệt là vào đêm Wed sau khi Tue phát hành. Xin lỗi nhưng tôi phải viết nhận xét này..Tại sao IDE thông minh không thể sửa tất cả các lỗi cho chúng tôi LOL
Mai

Câu trả lời:


53

Tại sao tôi phải bỏ đối tượng trả về Object.clone()?

Vì nó trở về Object.

Khung tổng quát khiến tôi nghĩ rằng IDE có thể kiểm tra loại tham chiếu đối tượng ở phía bên phải của dấu " = " mà không cần truyền trong khi tôi đang gõ? Tôi không hiểu

Object.clone không chung chung.

Nếu thuốc generic đã tồn tại khi cloneđược thiết kế, có lẽ nó sẽ trông như thế này (sử dụng tính đa hình F-Bounded):

interface Cloneable<T extends Cloneable<T>> {
  T clone();
}

Nếu Java có tính năng MyType, nó có thể trông như thế này:

interface Cloneable {
  this clone();
}

Nhưng Generics không tồn tại khi Object.cloneđược thiết kế và Java không có MyTypes, vì vậy phiên bản không an toàn kiểu Object.clonelà thứ chúng ta phải làm việc.


Tôi chỉ nhận ra rằng tính năng IDE làm tôi bối rối là trình biên dịch nền? Ý tôi là, đó là những gì cho phép hoàn thành mã và kiểm tra loại tự động với generic? Cá nhân, tôi thích trì hoãn kiểm tra loại cho đến khi biên dịch rõ ràng. Nhưng tôi thích hoàn thành mã.
konishiki 15/03/2016

1
@konishiki với suy luận kiểu Java 8 (và ở một mức độ nào đó là Java 7) , để cung cấp bất kỳ trợ giúp nào, IDE cần phải suy ra các loại. Điều này đòi hỏi phải biên dịch một phần. Trước khi suy luận kiểu, không cần biên dịch để tự động hoàn thành.
Boris the Spider

@BoristheSpider Cảm ơn rất nhiều về phản hồi đó! Tôi chắc chắn cần phải làm thêm một số thử nghiệm / suy nghĩ. rất nhiều đánh giá cao.
konishiki 15/03/2016

Tại sao bạn cần phải vượt qua original?
Clashsoft

@Clashsoft: Nghĩ ngu ngốc trong khi điều chỉnh phiên bản Lập trình chức năng rõ ràng. Cảm ơn.
Jörg W Mittag

26

Đây không phải là một tính năng của bất kỳ IDE, nhưng của định nghĩa ngôn ngữ.

Một IDE giúp bạn sử dụng ngôn ngữ lập trình hiệu quả hơn, nó không thay đổi ngữ nghĩa của ngôn ngữ đó. Điều đó có nghĩa là một người trợ giúp biên tập viên có thể tự động chèn một diễn viên khi rõ ràng bạn muốn cái nào, nhưng nó không thể đơn giản phá vỡ các quy tắc của ngôn ngữ và giả vờ rằng mã không biên dịch là hợp lệ.

Chỉnh sửa Đúng là một IDE có thể đóng gói trình biên dịch của riêng nó và trên thực tế, nhiều người thực hiện chính xác điều đó, ví dụ để báo cáo lỗi tốt hơn với nhiều thông tin bên trong vào cây phân tích một phần. Tuy nhiên, sẽ là một ý tưởng rất tồi khi để trình biên dịch nội bộ này triển khai các ngữ nghĩa ngôn ngữ khác với SDK chính thức, vì điều đó có nghĩa là mã hoạt động trong quá trình phát triển có thể bắt đầu thất bại một cách bí ẩn khi cài đặt trong sản xuất - các vấn đề theo định nghĩa không được định nghĩa gỡ lỗi!


Đây là những gì đã xảy ra: Tôi khá chắc chắn hoàn thành mã là một tính năng IDE (được thực hiện thông qua sự phản chiếu). Và việc kiểm tra kiểu tự động mà tôi đang nói đến xảy ra trong IDE (thông qua quá trình biên dịch nền). Tôi hy vọng đó là những gì đang xảy ra.
konishiki 15/03/2016

1
IDE có thể rất dễ dàng phá vỡ tất cả các quy tắc của đặc tả ngôn ngữ và chỉ cần biên dịch mã bằng mọi cách. Tôi biết cả NetBeans và Eclipse đều sử dụng các trình biên dịch riêng của họ. Vì vậy, trong những trường hợp IDE và trình biên dịch có hiệu quả giống nhau. Không nói rằng đó là một ý tưởng tốt, nhưng trình biên dịch C chắc chắn làm điều đó mọi lúc.
MichaelS

@MichaelS Đặc tả ngôn ngữ C được thiết kế để cho phép thay đổi đáng kể giữa các lần triển khai, để các nhà cung cấp khác nhau có thể chọn giữa các cách tiếp cận khác nhau có thể và thêm các tính năng bổ sung. Điều này tạo ra các khu vực mơ hồ khác nhau trong đặc tả, cần thiết để cho phép các biến thể đó. Tên "C" không được đăng ký nhãn hiệu, vì vậy không ai kiểm soát việc sử dụng thuật ngữ này. Đặc tả Java được thiết kế để loại bỏ sự mơ hồ nhất có thể và Java được đăng ký nhãn hiệu và chủ sở hữu nhãn hiệu thực thi rằng nó chỉ có thể được sử dụng trong các triển khai tuân thủ.
Jules

IDE hiện đại dù sao cũng cần một trình biên dịch. Gợi ý hoàn thành mã yêu cầu mã trước khi con trỏ được phân tích cú pháp. Và chắc chắn với generic (hoặc các mẫu C ++) yêu cầu một trình biên dịch đầy đủ, không chỉ là một trình phân tích cú pháp.
MSalters

3

Đó là do chữ ký loại của phương thức Object.clone. Chữ ký loại nói rằng phương thức sẽ trả về một đối tượng của loại Object.

protected Object clone() throws CloneNotSupportedException

Các bộ sưu tập sẽ sử dụng cái gọi là loại chung để thay thế kiểu đúc tự động.

Vì vậy, nếu bạn có mã này:

List<Integer> ints = Arrays.asList(1,2,3);
int x = ints.get(0);`

trình biên dịch sẽ thêm các phôi cho bạn đằng sau hậu trường, vì vậy mã thực sự sẽ là:

List ints = Arrays.asList(1,2,3);
int x = (Integer)ints.get(0);

0

Để hoàn thiện, kể từ Java 5, các kiểu trả về covariant được cho phép . Vì vậy, bạn có thể viết như sau:

public MyObject implements Cloneable {
  @Override
  public MyObject clone() {
    try {
      return (MyObject)super.clone();
    } catch (CloneNotSupportedException e) {
      throw new AssertionError();
    }
  }
}

Với điều này, mã sau đây là hợp pháp:

MyObject original = new MyObject();
MyObject clone = original.clone();
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.