2013-05-17 51 views
10

Tôi có đoạn mã sau:Tôi có thể khởi tạo một lớp ẩn danh trong hàm tạo của lớp ngoài không?

public class Outer { 
    public Interface Anony { 
     public void callback(); 
    } 

    public Outer() { 
     OtherClass.foo(new Anony() { 
      @Override 
      public void callback() { 
       .... 
      } 
     }); 
    } 
} 

Nhưng người bạn của tôi nói với tôi rằng có một số vấn đề trong đó. Tôi đã tạo một cá thể lớp ẩn danh trong hàm tạo của Bên ngoài, vì vậy cá thể lớp ẩn danh ngầm tham chiếu đến cá thể lớp bên ngoài, tức là Outer.this. Nhưng tại thời điểm này, thể hiện lớp bên ngoài chưa được tạo ra đầy đủ. Vì vậy, cá thể lớp ẩn danh tham chiếu một đối tượng với trạng thái không đầy đủ, do đó vấn đề.

Anh ấy có đúng không? Cảm ơn.

+0

Anony là một Giao diện, không phải lớp học! – zEro

+3

có, nhưng Anony mới() {...} đã tạo một cá thể lớp ẩn danh. Đúng. – Kai

+0

@zEro Vâng, 'Anony' là giao diện, nhưng đó là cú pháp để tạo các cá thể lớp ẩn danh thực hiện giao diện. Cú pháp tương tự được sử dụng khi khởi tạo các cá thể của các lớp ẩn danh mở rộng một lớp khác. – jpmc26

Trả lời

3

Bạn của bạn là đúng, nhưng tùy thuộc vào cách sử dụng của khóa học.

Sự cố không phải là tạo lớp bên trong bên trong hàm tạo. Vấn đề sẽ xảy ra NẾU lớp bên trong truy cập lớp bên ngoài.

Điều này là do bất kỳ đối tượng nào sẽ không thể cung cấp cho người được cấp bình thường bên trong một nhà xây dựng. Tất cả các biến cần thiết cho các hoạt động đối tượng có thể không được khởi tạo, v.v.

Tuy nhiên nếu lớp bên trong được đặt ở cuối hàm tạo, tôi không thấy vấn đề này xảy ra, nhưng hãy nhớ đây là một gambit nguy hiểm vì ai đó có thể thay đổi mã và sau đó nó là thời gian wtf với trình gỡ lỗi ...

0

tôi đã xây dựng một ví dụ brainf..k của tất cả các khả năng khác nhau tôi có thể nghĩ ra:

class OtherClass 
{ 
    public static void foo (final Anony x) 
    { 
    x.callback(); 
    } 
} 

public class Outer 
{ 
    public interface Anony 
    { 
    void callback(); 
    } 

    public class Inner implements Anony 
    { 
    public void callback() 
    { 
     System.out.println ("Inner.callback"); 
    } 
    } 

    public class InnerDerived implements Anony 
    { 
    public void callback() 
    { 
     System.out.println ("InnerDerived.callback"); 
    } 
    } 

    public static class StaticInner implements Anony 
    { 
    public void callback() 
    { 
     System.out.println ("StaticInner.callback"); 
    } 
    } 

    public Outer() 
    { 
    OtherClass.foo (new Anony() 
    { 
     public void callback() 
     { 
     System.out.println ("Anony.callback"); 
     } 
    }); 
    OtherClass.foo (new Inner()); 
    OtherClass.foo (new Inner() 
    { 
     @Override 
     public void callback() 
     { 
     System.out.println ("Anony.Inner.callback"); 
     } 
    }); 
    OtherClass.foo (new InnerDerived()); 
    OtherClass.foo (new InnerDerived() 
    { 
     @Override 
     public void callback() 
     { 
     System.out.println ("Anony.InnerDerived.callback"); 
     } 
    }); 
    OtherClass.foo (new StaticInner()); 
    OtherClass.foo (new StaticInner() 
    { 
     @Override 
     public void callback() 
     { 
     System.out.println ("Anony.StaticInner.callback"); 
     } 
    }); 
    } 
} 

các dự kiến đầu ra phải là:

Anony.callback 
Inner.callback 
Anony.Inner.callback 
InnerDerived.callback 
Anony.InnerDerived.callback 
StaticInner.callback 
Anony.StaticInner.callback 
1

Bạn có thể làm điều đó, nhưng bạn không nên.

Đây là ví dụ về mẫu chống được biết khác nhau là "cho phép thoát khỏi tham chiếu this từ hàm tạo" - chuyển tham chiếu tới đối tượng đang được xây dựng sang lớp khác từ bên trong hàm tạo. Lý do bạn không nên làm điều này là trong môi trường nhiều luồng, lớp mà tham chiếu đã được chuyển qua có thể thấy đối tượng mới trong một cấu trúc một phần được xây dựng và do đó trạng thái không phù hợp. Điều này có thể dẫn đến lỗi lạ và khó tìm. Điều này article của IBM là một trong nhiều mô tả nó.

Có gì không rõ ràng là cách nó đang xảy ra ở đây: lớp Anonymous đang thực sự nội lớp học, do đó, họ giữ một tham chiếu đến lớp chứa (ví dụ: this được xây dựng). Lớp người nhận OtherClass có thể thấy, và thậm chí hành động theo, this trước khi xây dựng hoàn thành.

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