2011-01-22 41 views
47

Tôi muốn gọi phương thức tĩnh riêng. Tôi có tên của nó. Tôi đã nghe nó có thể được thực hiện bằng cách sử dụng cơ chế phản chiếu Java. Tôi làm nó như thế nào?Làm cách nào để gọi phương thức tĩnh riêng tư bằng cách sử dụng phản chiếu (Java)?

EDIT: Một vấn đề tôi gặp phải khi cố gắng gọi phương thức là cách chỉ định loại đối số của nó. Phương thức của tôi nhận được một đối số và kiểu của nó là Map. Vì vậy, tôi không thể làm Map<User, String>.TYPE (Trong thời gian chạy không có một thứ như Bản đồ vì loại bỏ Java). Có cách nào khác để có được phương pháp này không?

+1

thử 'MyClass.class.getDeclaredMethod ("myMethod", Map.class); 'cho trường hợp của bạn – Cratylus

+0

Funnily đủ các generic thông tin của phương thức vẫn có sẵn khi chạy. 'Method.getGenericParameterTypes' –

Trả lời

79

Giả sử bạn muốn gọi MyClass.myMethod (int x);

Method m = MyClass.class.getDeclaredMethod("myMethod", Integer.TYPE); 
m.setAccessible(true); //if security settings allow this 
Object o = m.invoke(null, 23); //use null if the method is static 
+0

Cảm ơn. Phương thức của tôi nhận một tham số và kiểu của nó là Map . Do đó tôi không thể thực hiện 'Bản đồ .TYPE'. Có cách nào khác để có được phương pháp này không? – snakile

+6

@snakile: thử 'MyClass.class.getDeclaredMethod (" myMethod ", Map.class);' cho trường hợp của bạn – Cratylus

+3

Mọi thứ tôi được dạy trong trường đại học là một lời nói dối ... – rsy

0
Object insecure; //This needs to be an initialized reference 

Class c = insecure.getClass(); 
Method m = c.getMethod(name, parameterTypes); //Fill the name and types in 
m.setAccessible(true); 
m.invoke(insecure, parameters); //Fill in the parameters you would like 

Có một số trường hợp ngoại lệ kiểm tra có thể được ném. Cả hai parameterTypes và tham số là các đối số ellipse (độ dài biến đổi), điền chúng vào khi cần thiết. JVM theo đặc tả có một quy ước gọi mạnh mẽ, do đó bạn cần biết các kiểu tham số. Với điều đó đã nói, trừ khi bạn đang viết một số loại thùng chứa ứng dụng, thùng chứa thành phần máy chủ, hệ thống giống RMI hoặc ngôn ngữ dựa trên JVM, bạn nên tránh thực hiện điều này.

9

Invoke chính từ reflection tutorial

import java.lang.reflect.InvocationTargetException; 
import java.lang.reflect.Method; 
import java.util.Arrays; 

public class InvokeMain { 
    public static void main(String... args) { 
    try { 
     Class<?> c = Class.forName(args[0]); 
     Class[] argTypes = new Class[] { String[].class }; 
     Method main = c.getDeclaredMethod("main", argTypes); 
     String[] mainArgs = Arrays.copyOfRange(args, 1, args.length); 
     System.out.format("invoking %s.main()%n", c.getName()); 
     main.invoke(null, (Object)mainArgs); 

     // production code should handle these exceptions more gracefully 
    } catch (ClassNotFoundException x) { 
     x.printStackTrace(); 
    } catch (NoSuchMethodException x) { 
     x.printStackTrace(); 
    } catch (IllegalAccessException x) { 
     x.printStackTrace(); 
    } catch (InvocationTargetException x) { 
     x.printStackTrace(); 
    } 
    } 
} 
2

Không, bạn không thể nói Map<K,V>.class. Điều này là do loại tẩy xóa. Khi chạy, không có thứ gì như vậy.

May mắn thay, bạn có thể nói đồng bằng cũ Map.class. Đó là tất cả cùng một lúc thời gian chạy.

Nếu cảnh báo làm phiền bạn, hãy tìm kiếm các câu hỏi khác liên quan đến generics và loại xóa, có rất nhiều thông tin về chủ đề ở đây.

+0

+1 để chỉ ra loại tẩy xóa – snakile

1

Tôi sử dụng một phương pháp duy nhất đóng gói lấy phương pháp đích và sau đó gọi phương thức đó. Có lẽ có một số hạn chế, tất nhiên. Dưới đây là phương pháp đưa vào một lớp học và thử nghiệm JUnit của nó:

public class Invoker { 
/** 
* Get method and invoke it. 
* 
* @author jbetancourt 
* 
* @param name of method 
* @param obj Object to invoke the method on 
* @param types parameter types of method 
* @param args to method invocation 
* @return return value 
* @throws Exception for unforseen stuff 
*/ 
public static final <T> Object invokeMethod(final String name, final T obj, 
    final Class<?>[] types, final Object... args) throws Exception { 

    Method method = obj.getClass().getDeclaredMethod(name, types); 
    method.setAccessible(true); 
    return method.invoke(obj, args); 
} 

/** 
* Embedded JUnit tests. 
*/ 
@RunWith(JUnit4.class) 
public static class InvokerTest { 
    /** */ 
    @Test 
    public void testInvoke() throws Exception { 
     class TestTarget { 
      private String hello() { 
       return "Hello world!"; 
      } 
     } 

     String actual = (String) Invoker.invokeMethod("hello", 
       new TestTarget(), new Class<?>[] {}); 
     String expected = "Hello world!"; 
     assertThat(actual, is(expected)); 

    } 
} 

}

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