2013-07-05 36 views
51

tôi cố gắng để nhanh chóng các lớp bên trong định nghĩa trong mã Java sau:Làm thế nào để khởi tạo lớp bên trong với sự phản ánh trong Java?

public class Mother { 
     public class Child { 
      public void doStuff() { 
       // ... 
      } 
     } 
} 

Khi tôi cố gắng để có được một thể hiện của trẻ em như thế này

Class<?> clazz= Class.forName("com.mycompany.Mother$Child"); 
Child c = clazz.newInstance(); 

tôi nhận được ngoại lệ này:

java.lang.InstantiationException: com.mycompany.Mother$Child 
    at java.lang.Class.newInstance0(Class.java:340) 
    at java.lang.Class.newInstance(Class.java:308) 
    ... 

Tôi đang thiếu gì?

+2

Uhm, lớp bên trong của bạn không tĩnh ... Đây có phải là mục đích không? Đến từ một nền C# có thể? ;) – fge

+1

Cảm ơn bạn đã đề xuất ý tưởng "tĩnh"! Trong thực tế, sử dụng một lớp lồng nhau tĩnh thay vì một lớp bên trong làm cho cuộc sống của tôi dễ dàng hơn. – Stephan

+2

Vấn đề là, nếu một lớp bên trong không được khai báo tĩnh, các cá thể của lớp này phụ thuộc vào sự tồn tại của một cá thể của lớp bên ngoài; điều này khác với C# trong đó tất cả các lớp bên trong là "tĩnh" theo mặc định, và có thể được khởi tạo mà không có một cá thể mẹ. – fge

Trả lời

100

Có thông số "ẩn" bổ sung, là phiên bản của lớp kèm theo. Bạn sẽ cần phải nhận được hàm tạo bằng cách sử dụng Class.getDeclaredConstructor và sau đó cung cấp một thể hiện của lớp bao quanh làm đối số. Ví dụ:

// All exception handling omitted! 
Class<?> enclosingClass = Class.forName("com.mycompany.Mother"); 
Object enclosingInstance = enclosingClass.newInstance(); 

Class<?> innerClass = Class.forName("com.mycompany.Mother$Child"); 
Constructor<?> ctor = innerClass.getDeclaredConstructor(enclosingClass); 

Object innerInstance = ctor.newInstance(enclosingInstance); 

EDIT: Ngoài ra, nếu các lớp lồng nhau không thực sự cần phải tham khảo một ví dụ kèm theo, làm cho nó một lồng nhau tĩnh lớp thay vì:

public class Mother { 
    public static class Child { 
      public void doStuff() { 
       // ... 
      } 
    } 
} 
+1

Tôi tin rằng vấn đề thực sự là OP không có nghĩa là lớp học không phải là tĩnh để bắt đầu, nhưng tôi có thể bị nhầm – fge

+0

@fge: Có thể. Tôi sẽ đề cập đến điều đó trong câu trả lời. –

+6

Chỉ cần thêm một là nếu lớp bên trong không công khai, bạn cần phải gọi 'ctor.setAccessible (true)' để làm cho nó hoạt động! – Beccari

0

Mã này tạo thể hiện lớp bên trong.

Class childClass = Child.class; 
    String motherClassName = childClass.getCanonicalName().subSequence(0, childClass.getCanonicalName().length() - childClass.getSimpleName().length() - 1).toString(); 
    Class motherClassType = Class.forName(motherClassName) ; 
    Mother mother = motherClassType.newInstance() 
    Child child = childClass.getConstructor(new Class[]{motherClassType}).newInstance(new Object[]{mother}); 
Các vấn đề liên quan