2012-05-29 19 views
12

Có cú pháp Java nào để truy cập các phương thức mới được xác định trong các lớp bên trong vô danh từ lớp bên ngoài không? Tôi biết có thể có cách giải quyết khác nhau, nhưng tôi tự hỏi nếu một cú pháp đặc biệt tồn tại?Tôi có thể truy cập các phương thức mới trong lớp bên trong ẩn danh bằng một cú pháp nào đó không?

Ví dụ

class Outer { 

    ActionListener listener = new ActionListener() { 

     @Override 
     void actionPerformed(ActionEvent e) { 
      // do something 
     } 

     // method is public so can be accessible 
     public void MyGloriousMethod() { 
      // viva! 
     } 

    }; 

    public void Caller() { 
     listener.MyGloriousMethod(); // does not work! 
    } 


} 

GIẢI PHÁP RIÊNG CỦA TÔI

tôi chỉ di chuyển tất cả các phương pháp và các thành viên lên đến lớp bên ngoài.

Trả lời

18

Khi cá thể lớp ẩn danh đã được ẩn hoàn toàn vào loại được đặt tên, nó không thể bỏ qua vì không có tên cho loại ẩn danh. Bạn có thể truy cập các thành viên bổ sung của lớp bên trong vô danh thông qua this trong lớp, trong biểu thức ngay sau biểu thức và loại có thể được suy ra và trả về thông qua một cuộc gọi phương thức.

Object obj = new Object() { 
    void fn() { 
     System.err.println("fn"); 
    } 
    @Override public String toString() { 
     fn(); 
     return ""; 
    } 
}; 
obj.toString(); 



new Object() { 
    void fn() { 
     System.err.println("fn"); 
    } 
}.fn(); 


identity(new Object() { 
    void fn() { 
     System.err.println("fn"); 
    } 
}).fn(); 
... 
private static <T> T identity(T value) { 
    return value; 
} 
+0

Wow! Bạn biết trường hợp khi thành viên lớp ẩn danh CÓ THỂ được gọi! –

3

Người gọi của bạn biết listener dưới dạng ActionListener và do đó không biết gì về phương pháp mới đó. Tôi nghĩ cách duy nhất để làm điều này (ngoài việc làm thể dục dụng cụ phản chiếu, mà thực sự sẽ đánh bại mục đích sử dụng một lớp ẩn danh, tức là lối tắt/đơn giản) chỉ đơn giản là phân lớp ActionListener và không sử dụng một lớp ẩn danh.

+0

Yup. Giải pháp ở đây là ... không làm cho nó ẩn danh. –

+0

@Louis nếu tôi không làm cho nó ẩn danh tôi sẽ không đạt được từ nền kinh tế cú pháp. Tôi sẽ cần phải tạo ra một lớp và một thể hiện của nó. –

+0

@SuzanCioc: Bạn cũng tạo một lớp và một thể hiện của nó với mã hiện tại. Lớp học là vô danh, nhưng đó là sự khác biệt duy nhất. –

1

Không, không thể chịu được. Bạn sẽ cần phải cast ActionListener vào tên lớp con thực của nó, nhưng vì nó là ẩn danh, nó không có tên.

+0

Nhưng họ có thể tạo một số từ khóa cho điều này như 'listener.that.MyGloriousMethod()' hoặc '((Anonymous) listener) .MyGloriousMethod()' vì lớp ẩn danh không thực sự ẩn danh cho JVM nhưng chỉ là tên của lập trình viên và cho nên vấn đề chỉ là biểu thị nó bằng cách nào đó. –

+0

Họ có thể tưởng tượng ra điều gì đó, nhưng họ không làm vậy, bởi vì nó đã có thể thực hiện rất đơn giản: bằng cách tạo ra một lớp bên trong vô danh. –

1

Cách đúng để làm điều đó là sử dụng phản ánh:

import java.lang.reflect.InvocationTargetException; 

public class MethodByReflectionTest { 

    public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { 

     Object obj = new Object(){ 
      public void print(){ 
       System.out.println("Print executed."); 
      } 
     }; 

     obj.getClass().getMethod("print", null).invoke(obj, null); 
    } 
} 

Bạn có thể kiểm tra ở đây: How do I invoke a Java method when given the method name as a string?

5

Một sinh viên trong lớp học của tôi hỏi giáo sư của chúng tôi nếu điều này có thể được thực hiện vào ngày khác . Đây là những gì tôi đã viết như một bằng chứng tuyệt vời của khái niệm mà nó có thể được thực hiện, mặc dù không có giá trị nó, nó thực sự có thể và ở đây là làm thế nào:

public static void main(String[] args){ 

    //anonymous inner class with method defined inside which 
    //does not override anything 
    Object o = new Object() 
    { 
     public int test = 5; 
     public void sayHello() 
     { 
      System.out.println("Hello World"); 
     } 
    }; 

    //o.sayHello();//Does not work 

    try 
    { 
     Method m = o.getClass().getMethod("sayHello"); 
     Field f = o.getClass().getField("test"); 
     System.out.println(f.getInt(o)); 
     m.invoke(o); 
    } catch (Exception e) 
    { 
     e.printStackTrace(); 
    } 
} 

Bằng cách sử dụng các lớp Phương pháp Java của chúng ta có thể gọi một phương pháp bằng cách truyền giá trị chuỗi và các tham số của phương thức. Điều tương tự có thể được thực hiện với các trường.

Chỉ cần nghĩ rằng sẽ thật thú vị khi chia sẻ điều này!

0

Có bạn có thể truy cập vào phương pháp này xem ví dụ dưới đây nếu có nghi ngờ gì nữa hãy bình luận

package com; 
interface A 
{ 
    public void display(); 
} 
public class Outer { 
    public static void main(String []args) 
    { 
     A a=new A() { 
     @Override 
     public void display() { 
      System.out.println("Hello"); 
     } 
    }; 
     a.display(); 
    } 
    } 
Các vấn đề liên quan