문제

Java에서 반사 방법 호출을해야합니다. 이러한 호출에는 원시 유형 (int, double 등) 인 인수가있는 방법이 포함됩니다. 반사적으로 메소드를 찾을 때 이러한 유형을 지정하는 방법은 int.class, double.class 등입니다.

문제는 유형을 동적으로 지정할 외부 소스에서 입력을 수락한다는 것입니다. 따라서이 수업 참조도 동적으로 제시해야합니다. 구분 된 파일을 상상해보십시오. 매개 변수 유형 목록이있는 메소드 이름 목록을 상상해보십시오.

doSomething int double
doSomethingElse java.lang.String boolean

입력이 같은 경우 java.lang.String, 나는 내가 사용할 수 있다는 것을 안다 Class.forName("java.lang.String") 해당 클래스 인스턴스로 돌아갑니다. 원시 유형 클래스를 되 찾기 위해 해당 방법을 사용하는 방법이 있습니까?

편집하다:모든 응답자에게 감사합니다. 내가 원하는 것을 깨끗하게 할 수있는 내장 방법이 없다는 것이 분명해 보이기 때문에 재사용 할 것입니다. ClassUtils 스프링 프레임 워크에서 클래스. 내 요구 사항과 함께 작동하는 클래스 .forname ()을 대체하는 것으로 보입니다.

도움이 되었습니까?

해결책

스프링 프레임 워크에는 유틸리티 클래스가 포함되어 있습니다 분류 정적 메소드 Forname을 포함합니다. 이 방법은 귀하가 설명한 정확한 목적으로 사용될 수 있습니다.

봄에 의존하는 것을 좋아하지 않는 경우 : 메소드의 소스 코드 찾을수있다 이자형. g. 여기 공공 저장소에서. 클래스 소스 코드는 Apache 2.0 모델에 따라 라이센스가 부여됩니다.

그러나 알고리즘은 원시 유형의 하드 코딩 된 맵을 사용합니다.


편집하다: 댓글 작성자 Dávid Horváth와 Patrick에게 깨진 링크를 지적한 것에 감사드립니다.

다른 팁

그만큼 Class 기본 유형의 인스턴스는 예를 들어 사용했듯이 얻을 수 있습니다. int.class, 그러나 같은 것을 사용하여 동일한 값을 얻는 것도 가능합니다. Integer.TYPE. 각 원시 래퍼 클래스에는 정적 필드가 포함되어 있으며 TYPE, 해당 원시 클래스 인스턴스가 있습니다.

당신은 기본 클래스를 통해 원시 클래스를 얻을 수 없습니다 forName, 그러나 쉽게 구할 수있는 수업에서 얻을 수 있습니다. 반사를 절대적으로 사용해야한다면 다음과 같은 것을 시도 할 수 있습니다.

Class clazz = Class.forName("java.lang.Integer");
Class intClass = clazz.getField("TYPE").get(null);

intClass.equals(int.class);         // => true

아마도 프리미티브를 매핑하기 만하면 나머지 클래스의 경우 "Forname"메소드를 수행합니다.

나는 다음과 같은 일을 할 것입니다.

void someWhere(){
     String methodDescription = "doSomething int double java.lang.Integer java.lang.String"
     String [] parts = methodDescription.split();
     String methodName= parts[0]
     Class [] paramsTypes = getParamTypes( parts ); // Well, not all the array, but a, sub array from 1 to arr.length..  

    Method m = someObject.class.getMethod( methodName, paramTypes );
    etc. etc etc.
}

public Class[] paramTypes( String [] array ){
     List<Class> list = new ArrayList<Class>();
     for( String type : array ) {
         if( builtInMap.contains( type )) {
             list.add( builtInMap.get( type ) );
          }else{
             list.add( Class.forName( type ) );
          }
     }
     return list.toArray();
}  

    // That's right.
Map<String,Class> builtInMap = new HashMap<String,Class>();{
       builtInMap.put("int", Integer.TYPE );
       builtInMap.put("long", Long.TYPE );
       builtInMap.put("double", Double.TYPE );
       builtInMap.put("float", Float.TYPE );
       builtInMap.put("bool", Boolean.TYPE );
       builtInMap.put("char", Character.TYPE );
       builtInMap.put("byte", Byte.TYPE );
       builtInMap.put("void", Void.TYPE );
       builtInMap.put("short", Short.TYPE );
}

즉, 프리미티브 유형이 저장되는 맵을 만듭니다. 설명이 원시인에 속하면 매핑 클래스를 사용하십시오. 이 맵은 외부 구성 파일에서로드하여 유연성을 추가하여 java.lang.string 대신 내장으로 문자열을 추가하거나 잠재적으로 이와 같은 방법을 갖습니다.

"DoSomething String 예 | 아니오"

Struts, Hibernate, Spring 및 Apache Libs와 같은 OS 프로젝트에는 이러한 종류의 코드가 많이 있으므로 (몇 가지 언급). 0에서 시작할 필요가 없습니다.

BTW. 위의 코드를 컴파일하지는 않았지만 수정이 거의없는 상태로 작동하지 않다고 확신합니다.

Apache Commons Lang 가지다 classutils.getClass (문자열), 원시 유형을 지원합니다.

많은 클래스 방법은 불행히도 일관된 방식으로 프리미티브를 처리하지 않습니다. Forname에서 이것에 대한 일반적인 방법은 다음과 같은 테이블을 갖는 것입니다.

private static final Map<String, Class> BUILT_IN_MAP = 
    new ConcurrentHashMap<String, Class>();

static {
    for (Class c : new Class[]{void.class, boolean.class, byte.class, char.class,  
            short.class, int.class, float.class, double.class, long.class})
        BUILT_IN_MAP.put(c.getName(), c);
}

public static Class forName(String name) throws ClassNotFoundException {
    Class c = BUILT_IN_MAP.get(name);
    if (c == null)
        // assumes you have only one class loader!
        BUILT_IN_MAP.put(name, c = Class.forName(name));
    return c;
}

다음 코드는 필드 이름이 알려진 원시 유형의 클래스를 얻는 방법에 대해 이야기합니다.

public class CheckPrimitve {
    public static void main(String[] args) {
        Sample s = new Sample();
        try {
            System.out.println(s.getClass().getField("sampleInt").getType() == int.class); // returns true
            System.out.println(s.getClass().getField("sampleInt").getType().isPrimitive()); // returns true
        } catch (NoSuchFieldException e) {          
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }       
    }
}

class Sample {
    public int sampleInt;
    public Sample() {
        sampleInt = 10;
    }
}

주어진 값이 각 래퍼 클래스인지 필드 값을 얻음으로써 주어진 값이 원시적인지 아닌지 확인할 수 있습니다.

    public class CheckPrimitve {
        public static void main(String[] args) {
            int i = 3;
            Object o = i;
            System.out.println(o.getClass().getSimpleName().equals("Integer")); // returns true
            Field[] fields = o.getClass().getFields();
            for(Field field:fields) {
                System.out.println(field.getType()); // returns {int, int, class java.lang.Class, int}
            }
        }
    }

Google Guava가 제공합니다 com.google.common.primitives.Primitives 이런 종류의 물건을 위해.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top