2013-06-05 33 views
5

Tôi không chắc chắn cách hoạt động của từ khóa new trong Java. Có chắc chắn rằng mỗi khi tôi sử dụng từ khóa new, một đối tượng mới sẽ được tạo trên heap?Vai trò của từ khóa mới trong Java

Tôi đã nghi ngờ điều này khi tôi đang học sau example-

class Mixer { 
    Mixer() { } 
    Mixer(Mixer m) { m1 = m; } 
    Mixer m1; 
    public static void main(String[] args) { 
    Mixer m2 = new Mixer(); 
    Mixer m3 = new Mixer(m2); // Does it create any new mixer object? 
    m3.go(); 
    Mixer m4 = m3.m1;   m4.go(); 
    Mixer m5 = m2.m1;   m5.go(); 
    } 
    void go() { System.out.print("hi "); } 
} 

Dòng Mixer m3 = new Mixer(m2); gọi một constructor mà không tạo ra bất kỳ đối tượng mới. Vì vậy, nó là không có đối tượng mới được tạo ra?

Ngoài ra, Biến nào đề cập đến đối tượng nào ở cuối chương trình, tức là cho đến khi chúng tôi nhận được NullPointerExcetion cho biến m5.

+1

Điều gì khiến bạn nghĩ rằng nó không tạo ra một đối tượng mới? –

+0

http://docs.oracle.com/javase/tutorial/java/javaOO/objectcreation.html –

+0

@ DaveNewton- Nếu đối tượng mới được tạo thì biến nào đang đề cập đến biến đó? –

Trả lời

2

mới luôn tạo một phiên bản mới (vì vậy hãy luôn đặt trước bộ nhớ heap, v.v.).

Điều này sẽ minh họa điều đó. lưu ý rằng == trên một cá thể sẽ cho bạn biết nếu nó là cùng một cá thể (đối tượng) hoặc một đối tượng khác. (đó là lý do tại sao bạn nên luôn luôn sử dụng bằng, trừ khi đây là những gì bạn muốn làm)

Tôi đã thêm một điều buồn cười xảy ra với chuỗi. "abc" không tạo một phiên bản mới, nhưng tái sử dụng một phiên bản hiện có. nhưng khi bạn gọi mới trên lớp String nó.

public class Test { 
    private String value; 

    public String getValue() { 
     return value; 
    } 

    public Test() { 
     value = "default"; 
    } 
    public Test(Test t) { 
     this.value = t.getValue(); 
    } 

    public Test(String value) { 
     this.value = value; 
    } 

    public static void main(String[] argv) { 
     Test t1 = new Test(); 
     Test t2 = new Test(t1); 

     if (t1 == t2) { 
      System.out.println("t1 == t2. should not happen"); 
     } else { 
      System.out.println("t1 is a different instance from t2"); 
     } 

     String s1 = "test"; 
     String s2 = "test"; 

     if (s1 == s2) { 
      System.out.println("s1 == s2. strings initialized with quotes don't always get a new instance."); 
     } else { 
      System.out.println("s1 is a different instance from s2. should not happen"); 
     } 

     String s3 = new String("test"); 
     String s4 = new String(s3); 

     if (s3 == s4) { 
      System.out.println("s3 == s4. should not happen."); 
     } else { 
      System.out.println("s3 is a different instance from s4, as they were newed."); 
     } 

    } 
} 
10

Có - mỗi khi bạn sử dụng new (làm từ khóa), một đối tượng mới sẽ được tạo. Trong trường hợp này:

Mixer m3 = new Mixer(m2); 

Dòng Mixer m3 = new Mixer (m2); gọi một hàm tạo không tạo ra bất kỳ đối tượng mới nào.

Lý do của bạn hoàn toàn không chính xác. Một Mixer mới đang được tạo bằng cách sử dụng m2 làm tham số. Thông thường, điều này chỉ ra một hàm tạo bản sao - tạo một Bộ trộn mới với các thuộc tính giống như cũ (nhưng nó luôn là một đối tượng riêng biệt mới, và không kỹ thuật để sao chép các thuộc tính của đối tượng được truyền vào.)

+1

Và m5 gây ra NPE vì nó * là * null. (Thiết lập để m2.m1 là null) – Fildor

+0

Nhưng m2 chỉ là biến tham chiếu đến đối tượng trộn "cũ" và đang được truyền trong cấu trúc Mixer. Điều này thực sự tạo ra một biến tham chiếu mới cho đối tượng trộn "cũ", phải không? –

+0

'm2' không phải là null - nhưng' m2' được tạo mà không có tham số, vì vậy trường 'm1' của nó là rỗng (và đây là nguyên nhân gây ra NPE,' m2.m1') – berry120

1

Từ quan điểm của lập trình viên, new làm cho việc tạo đối tượng mới.

Tuy nhiên, trình biên dịch có thể thực hiện escape analysis để xác định xem đối tượng có thực sự cần được tạo trên heap khi chạy hay không.

Đối với câu hỏi cuối cùng, mã của bạn tạo hai đối tượng. Một tham chiếu bằng m2, m3.m1 và m4, và cái còn lại được tham chiếu bằng m3.

+0

Tôi không biết điều đó, cảm ơn bạn. – Djon

1

Trước hết, hãy quên phân biệt ngăn xếp/đống - đó là chi tiết triển khai của trình biên dịch hoặc thời gian chạy (tùy thuộc vào ngôn ngữ được đề cập). Nó có thể tạo sự khác biệt nếu bạn đang làm lập trình hệ thống trong C hoặc assembly, nhưng không phải khi bạn đang làm việc trong các ngôn ngữ và môi trường được thu gom rác như Java hoặc .NET.

Và để trả lời câu hỏi của bạn: new thực sự làm hai việc với hầu hết các ngôn ngữ (?) (Tất cả?) Có toán tử như vậy. Nó đầu tiên cấp phát bộ nhớ ở đâu đó để giữ một thể hiện của kiểu, và sau đó gọi một hàm khởi tạo để khởi tạo một cá thể của kiểu trong bộ nhớ mới được cấp phát đó. Xây dựng chuỗi sau đó có thể gây ra các nhà xây dựng khác được gọi (hoặc trên cùng một loại, lớp cơ sở/superclasses của loại, hoặc bất cứ điều gì mà constructor loại cần phải làm công việc của mình).

Như được chỉ ra bởi @berry120, một hàm tạo tham số cùng loại với kiểu mà hàm tạo là dành cho thường chỉ cho biết một hàm tạo bản sao. Một cách khác để đạt được cùng một kết quả là có và thực hiện một cuộc gọi rõ ràng đến một cái gì đó giống như một phương thức clone() trả về một bản sao của đối tượng mà nó được gọi.

0

Nó tạo đối tượng mới và hàm tạo của nó được chuyển một tham chiếu đến đối tượng khác m2 mà bạn đã tạo.

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