2009-07-02 28 views
5

Có cách nào trong Java rằng một tuyên bố nhưTrong Java, mới luôn mới?

Thing thing = new Thing(); 

thể không kết quả trong một đối tượng mới được tạo ra (ví dụ: bất kỳ cách nào mà thing có thể sẽ trỏ đến một đối tượng đã tồn tại)?

+2

Tại sao bạn hỏi? Bạn đang nhận được hành vi kỳ lạ ở đâu đó? –

+2

Không có hành vi lạ. Chỉ cần tò mò - tôi đã đọc về hàm tạo Integer (int i) - điểm được tạo ra là phương thức tĩnh Integer.valueOf (int i) có thể tốt hơn vì nó sẽ tái sử dụng các đối tượng khi cần - Tôi muốn kiểm tra xem nó có thể không , không chỉ độc đáo, cho một nhà xây dựng để làm điều tái sử dụng. –

+8

Đúng, không thể. Trong C++, bạn có thể ghi đè toán tử 'new', nhưng bạn không thể sử dụng Java. Điều đó không làm tôi buồn. –

Trả lời

16

Toán tử new phân bổ không gian vùng heap mới và gọi hàm tạo. Bạn sẽ luôn luôn nhận được một đối tượng mới theo cách đó (trừ khi, như những người khác đã chỉ ra, một ngoại lệ được ném vào hàm tạo).

Điều này hơi khác với phương pháp tĩnh trả lại tham chiếu, chẳng hạn như Integer.valueOf() sử dụng lại các đối tượng từ một nhóm nội bộ nếu có thể.

+1

Đúng và nó thậm chí còn là một mẫu được đề xuất trong các giá trị "Hiệu quả Java" tuyệt vời của Joshua Bloch –

6

Nếu hàm tạo cho Thing ném ngoại lệ, đối tượng không được tạo. Tuy nhiên, thing sẽ không bao giờ trỏ đến một phiên bản Thing hiện có khác.

+0

cũng như các giá trị 'null'. Thật lạ khi thấy mã như 'Thing t = new Thing(); if (t == null) ... '- nó sẽ không bao giờ xảy ra –

0

Không, trong trường hợp không có bộ nhớ trong đó, bạn sẽ nhận được lỗi OutOfMemoryError.

Tất nhiên, có thể có các trường hợp ngoại lệ khác do trình tạo Thing đưa ra.

+0

hmmm, tại sao không phải là một OutOfMemoryError? Chỉ quan tâm. –

+0

ngoại lệ chính xác thực sự là OutOfMemoryError. – cd1

+0

@ CD1 @Tim Đã sửa lỗi. Tôi biết đó là một cái gì đó như thế. –

0

Tôi không chắc chắn nếu tôi hiểu câu hỏi của bạn một cách chính xác.

Định nghĩa mới là để cấp phát và khởi tạo đối tượng mới.

Tôi đoán bạn có thể lưu trữ một tham chiếu tĩnh vào một đối tượng và sau đó sao chép nó để tạo một đối tượng mới, nhưng đối tượng đó vẫn sẽ là mới.

Vì bạn không thể sửa đổi giá trị this (nếu không bạn chỉ có thể nói điều gì đó như this = oldObject trong hàm tạo của mình), cách duy nhất bạn có thể làm là ném ngoại lệ, như đã được đề cập trước đó.

0

theo như tôi biết nó không giống như C++ nơi bạn có thể quá tải operator new hoặc làm vị trí mới hoặc những thứ phân bổ khác. (nhưng tôi không quen thuộc với JLS)

3

Sử dụng new sẽ luôn dẫn đến một đối tượng mới được phân bổ và tạo. Tuy nhiên, bạn có thể đề cập đến khái niệm interning, nơi các đối tượng và được lưu trữ trong một hồ bơi và có thể được tái sử dụng để tiết kiệm không gian. Để có một ví dụ điển hình, hãy xem bài viết này trên String interning trong Java.

1

Mới luôn luôn mới (có thể có một số ngoại lệ cho trình bao bọc nguyên thủy), nhưng nếu sử dụng lại đối tượng là hành vi mong muốn, có nhiều cách để thực hiện điều đó thông qua một số mẫu thiết kế (singleton, factory, pool etc.).

+1

Trình bao bọc nguyên thủy (còn được gọi là nguyên thủy đóng hộp) tuân theo các quy tắc giống như bất kỳ lớp nào khác: nếu bạn sử dụng một hàm tạo để tạo, bạn luôn nhận được một cá thể mới. Tuy nhiên, việc tự động tạo không nhất thiết phải tạo một đối tượng duy nhất mỗi lần bởi vì nó sử dụng một phương thức factory thay vì một hàm tạo. –

+0

Tôi có nói đôi điều khác biệt không? – quosoo

+1

Mới luôn mới. Không có ngoại lệ, ngay cả đối với các trình bao bọc nguyên thủy. – dave4420

-1

Trong Java, điều duy nhất tôi có thể nghĩ đến là sử dụng mẫu Singleton. Điều này sẽ không tạo ra nhiều phiên bản mới của Thing, mà là một cá thể của cùng một đối tượng mỗi lần.

+1

Bất cứ khi nào bạn sử dụng 'mới', bạn đang tạo một phiên bản mới. Giai đoạn. Với mẫu Singleton, bạn đang gọi 'SingletonClass.getInstance() ', không phải là' SingletonClass() mới '. –

4

Một số người đang nói rằng một đối tượng sẽ không được tạo nếu người xây dựng ném một ngoại lệ. Tôi chỉ muốn chỉ ra rằng điều này là không đúng sự thật.Như một ví dụ, hãy xem xét mã rất xấu này:

public class Test { 
    static int count; 

    static Set<Test> set = new HashSet<Test>(); 

    int id = count++; 


    public Test() { 
     set.add(this); 
     throw new RuntimeException(); 
    } 


    public static void main(String[] args) throws Exception { 
     for(int i = 0; i < 5; i++) { 
      try { 
       new Test(); 
      } catch(Exception e) { 
      } 
     } 
     System.out.println(set); 
    } 


    public String toString() { 
     return "Test[" + id + "]"; 
    } 
} 

Đầu ra là:

[Test[0], Test[1], Test[2], Test[4], Test[3]] 

new tạo ra một đối tượng mới MỌI LÚC NÀO.

0

mới luôn tạo đối tượng mới. Trong java bạn không thể tái sử dụng đối tượng bằng cách sử dụng mới. Thực sự điều này dẫn đến vấn đề hiệu suất trong lớp java nhất định. Ví dụ: Lớp Boolean thực tế chỉ có thể lưu trữ hai giá trị (đúng hoặc sai), người dùng vẫn có thể tạo nhiều đối tượng có cùng giá trị bằng cách sử dụng mới.

0

số

Sau khi thực hiện mà dòng mã thing sẽ không bao giờ tham khảo một đối tượng đã tồn tại trước dòng đó.

0

Cuộc gọi tới new có thể bị lỗi nếu đây là lần đầu tiên bạn tham chiếu đến lớp học và nếu lớp đó có các khối tĩnh không khởi tạo được. Tôi đã gặp các hành vi trong đó bất kỳ lỗi thời gian chạy nào xảy ra trong một khối tĩnh hoặc hàm tạo sẽ dẫn đến cuộc gọi mới ném ra một ngoại lệ ClassNotFound trong ngữ cảnh sử dụng trong máy chủ ứng dụng websphere. Trình tải lớp websphere dường như từ chối lớp tải vì ngoại lệ thời gian chạy.

Các vấn đề liên quan