2010-04-08 3 views
22

간단한 질문입니다. 어떻게이 코드가 작동합니까?varargs 및 리플렉션 작업 방법

public class T { 

    public static void main(String[] args) throws Exception { 
     new T().m(); 
    } 

    public // as mentioned by Bozho 
    void foo(String... s) { 
     System.err.println(s[0]); 
    } 

    void m() throws Exception { 
     String[] a = new String[]{"hello", "kitty"}; 
     System.err.println(a.getClass()); 
     Method m = getClass().getMethod("foo", a.getClass()); 
     m.invoke(this, (Object[]) a); 
    } 
} 

출력 :

class [Ljava.lang.String; 
Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
     at java.lang.reflect.Method.invoke(Method.java:597) 

답변

41
Test.class.getDeclaredMethod("foo", String[].class); 

작품. 문제는 getMethod(..)public 메서드 만 검색한다는 것입니다.

Returns a Method object that reflects the specified public member method of the class or interface represented by this Class object.

업데이트 : 성공적으로하는 방법을 점점 후에는 사용하여 호출 할 수 있습니다 : javadoc 내에서

m.invoke(this, new Object[] {new String[] {"a", "s", "d"}}); 

입니다 - String 배열 - 하나 개의 요소로 새로운 Object 배열을 만들 수 있습니다. 당신의 변수 이름이 보일 것 같은 :

m.invoke(this, new Object[] {a}); 
+0

감사! 하지만 지금은 그 호출에 집착합니다. – PeterMmm

+0

다시 한번 감사드립니다! 못 봤어. – PeterMmm

+0

'invoke'솔루션 +1; 그건 더러운 것입니다. – polygenelubricants

8

// 편집하기 전에 :

귀하의 문제가 getMethodpublic 멤버를 찾습니다 있다는 사실이다. Class.getMethod (강조 광산)에서

:

Returns a Method object that reflects the specified public member method of the class or interface represented by this Class object

그래서 당신은 두 가지 옵션이 있습니다

  • public void foo(String... s)을 확인하고 getMethod
  • 대신 사용

getDeclaredMethod를 사용을 그 같은 차이가 존재한다. r getField/sgetDeclaredField/sgetConstructor/sgetDeclaredConstructor/s입니다.


// invoke 문제

이 특히 불쾌한이지만,이 주조 할 수 있기 때문에 무슨 일하는 것은, 당신이 유일한 인수로 참조 형의 배열을 전달해야하는 경우 invoke(Object obj, Object... args) 그것을 교묘하게한다는 것입니다 대신 new Object[1] 안에 포장해야하지만 Object[]으로 변경하십시오.

당신은 할 수 있습니다 :

m.invoke(this, new Object[] {a}); // Bohzo's solution 

이는 가변 인자의 메커니즘을 무시합니다. 더 간결 당신은 또한 수행 할 수 있습니다

m.invoke(this, (Object) a); 

Object에 대한 캐스트는 가변 인자 메커니즘은 당신을위한 배열을 만드는 작업을 할 수 있습니다.

null을 인수로 varargs에 전달할 때도 트릭이 필요하며 리플렉션과 관련이 없습니다.

public void foo(String... ss) { 
    System.out.println(ss[0]); 
} 

    foo(null); // causes NullPointerException 
    foo((String) null); // prints "null" 
+1

+1,이 캐스트 물건에 좋은 – PeterMmm

+0

@ polygenelubricants, 내 경우는 : void foo() 함수에 인수 Param ... param (힌트 : Param은 generic 형식 임) 대신 String ... s. 새로운 Object [] {new URL ("google.com")}을 사용했지만 다음 오류가 발생합니다. IllegalArgumentException : 인수 1에 java.lang.Object [유형이 있어야하며 java.net.URL이 있어야합니다. 미리 감사드립니다. – MapleLover