2012-08-28 2 views
3

Java에서 Reflection API를 사용하여 파일을 구문 분석 한 후 런타임에 클래스를 생성하는 것과 관련된 솔루션을 만들었습니다.바인딩 - Java

while ((line = textReader.readLine()) != null) 
    { 
     Pattern p = Pattern 
      .compile("([^:]+):([^:]+)::([\\d]+)::([^:]+)::(.+)"); 
     Matcher m = p.matcher(line); 
     if (m.find()) 
     { 
      String id = m.group(1); 
      String className = m.group(2); 
      int orderOfExecution = Integer.valueOf(m.group(3)); 
      String methodNameOrNew = m.group(4); 
      Object[] arguments = m.group(5).split("::"); 
      if (methodNameOrNew.compareTo("new") == 0) 
      { 
       System.out.println("Loading class: " + className); 
       if (className.contains("Competition")) 
       { 
        continue; 
       } 
       else if (className.contains("$")) 
       { 
        continue; 
       } 
       else 
       { 
        Class<?> cl = Class.forName(className); 
        printMembers(cl.getConstructors(), "Constructor"); 
        Constructor<?>[] cons = cl.getConstructors(); 
        Object obj = cons[0].newInstance(arguments); 
        this.map.put(id, obj); 
       } 
      } 
     } 
    } 

printMembers() :

Loading class: org.powertac.common.TariffSpecification 
Constructor: 
    public org.powertac.common.TariffSpecification(org.powertac.common.Broker,org.powertac.common.enumerations.PowerType) 

java.lang.IllegalArgumentException: argument type mismatch 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:525) 
    at Parser.parse(Parser.java:64) 
    at Parser.main(Parser.java:137) 

arguments[]은 다음과 같습니다 : 1 : CONSUMPTION

private static void printMembers(Member[] mbrs, String s) 
{ 
    out.format("%s:%n", s); 
    for (Member mbr : mbrs) 
    { 
     if (mbr instanceof Field) 
      out.format(" %s%n", ((Field) mbr).toGenericString()); 
     else if (mbr instanceof Constructor) 
      out.format(" %s%n", ((Constructor) mbr).toGenericString()); 
     else if (mbr instanceof Method) 
      out.format(" %s%n", ((Method) mbr).toGenericString()); 
    } 
    if (mbrs.length == 0) 
     out.format(" -- No %s --%n", s); 
    out.format("%n"); 
} 

그러나, 나는 다음과 같은 오류가 발생합니다. 올바른 생성자를 만들고 적절한 인수 (유형)를 부여하려면 어떻게해야합니까? 예를 들어 , 샘플 파서 내가 사용하고 내가 가진 :

2233:org.powertac.common.Tariff::6::new::6 

그때 내가 유형 org.powertac.common.Tariffclass (new 새로운 오브젝트가 작성 될 필요하고, 그것이 double rate 소요 하더군요을 만들어야합니다 이 경우에는 6인데, double이면 인수가 String (6)이됩니다. 올바른 유형으로 생성/변환/캐스팅을하고 생성자에 할당 할 수 있습니까? 첫 번째 생각은 기호 테이블을 만드는 것이었지만 더 쉬운 해결책에 대해 궁금합니다.

+0

호기심 때문에, 일반적으로 해결하려는 것은 무엇입니까? 그리고 표준 Java 직렬화 메커니즘 (직렬화 API, xml/json에 지속성 등)을 사용하지 않는 이유 – udalmik

+0

@mudalov 좀 더 자세한 정보를 제공 할 수 있습니까? – cybertextron

답변

3

당신은 당신이 당신의 예에서 Constructor.newInstance(Object...)

내가 1 : CONSUMPTION 당신이

Object[] arguments = new Object[]{Integer.valueOf(1), "CONSUMPTION"}; 
에 배열 동등한 의미의 배열을 생각하는거야에 통과 할 인수에 적합한 생성자를 선택 Class.getConstructor(Class...)를 사용할 필요가

그래서 당신은 호출 당신이 당신의 인수의 유형을 알 수없는 경우

Class clazz = ... //Whatever class reference you have 
Constructor c = clazz.getConstructor(Integer.class, String.class); 
Object obj = c.newInstance(arguments); 

다음 당신은에 의해 반환 된 클래스의 배열에 대해 설정하는 인수를 테스트해야합니다 각각의 생성자에 대해 210은 인수 배열과 일치하는 생성자를 찾을 때까지 Class.getConstructors()에 의해 반환됩니다. 보다 구체적으로, 인수 배열과 클래스 배열은 길이가 같고 클래스 배열의 각 클래스는 인수 배열의 같은 위치에있는 값의 클래스에 대해 Class.isAssignableFrom(Class)을 전달합니다. 생성자에 전달하고 싶은대로 인수 배열을 가지고 당신이해야합니다 이것을 사용하기 위해 코드

public boolean canConstruct(Object[] args, Constructor<?> c){ 
     Class<?>[] paramTypes = c.getParameterTypes(); 
     if(args.length != paramTypes.length){ 
      return false; 
     } 

     int i = 0; 
     for(Object arg: args){ 
      if(!paramTypes[i].isAssignableFrom(arg.getClass())){ 
       return false; 
      } 
        i++; 
     } 

     return true; 
    } 

에서 위의

구현. 입력 정보를 편집하여 유형 정보 (java serialization 작동 방식과 유사 함)를 포함하도록하여 해당 유형 생성자를 사용하여 리플렉션을 통해 생성자 인수 배열에 대한 인수를 구성 할 수 있습니다.

+0

좀 더 자세한 정보를 제공 할 수 있습니까? – cybertextron

+0

@philippe 답변에 좀 더 자세히 설명해주었습니다. – Dev

+0

'Constructor.newInstance (Object ...) '에 전달한 값이'Constructor'에 의해 반환 된 Class 배열에 의해 표현되는 클래스에 할당 될 수 없다면,getParameterTypes()'를 정확한 순서로 올바른 인수와 함께 사용하면 질문에 위와 같이 인수 유형 불일치 예외가 표시됩니다. – Dev

관련 문제