2013-04-16 4 views
7

I 효과적으로이 작업을 수행하는 일반적인 방법을 만들고 싶습니다가 더 Number.valueOf() 방법은 없습니다 및 0 캐스트 할 수없는 T.자바 제네릭 및 숫자 유형

사용 예제 :

String value = "0.00000001"; 

System.out.println("Double: " + MyClass.<Double>sloppyParseNumber(value)); 
System.out.println("Float: " + MyClass.<Float>sloppyParseNumber(value)); 

double d = MyClass.sloppyParseNumber(value); 
float f = MyClass.sloppyParseNumber(value); 

는 자바 가능한 일반적인 방법 위에 구현되어 있습니까? 그렇다면 어떻게? 그렇다면 좋은 대체 접근 방법은 무엇입니까?


편집 : 몇 가지 가능한 중복이있는 것으로 보이지만 정확히 이것을 다루는 하나를 찾지 못했습니다. 이 2 가지 연산을 허용하는 몇 가지 트릭이 필요합니다. Number 서브 클래스의 문자열을 구문 분석하고 Number 하위 클래스의 0 값을 반환하십시오.

+1

['Number'] (http://docs.oracle.com/javase/6/docs/api/java/lang/Number.html) 추상 클래스는 파싱이 특정 유형에 의해 수행되기 때문에 string을 유형으로 구문 분석하는 메소드를 포함하지 않습니다. 제안은 제네릭을 사용하지 않고 '... ToInteger','... ToDouble' 등과 같은 함수를 만드는 것입니다. –

+0

나는 쉬운 방법이 없다고 생각합니다. 나는 단순히 'new MyClass (value) .asDouble();'과 같은 것을 사용하고 asInteger, asLong, asFloat, asDouble 등의 메소드를 수동으로 구현한다. – assylias

+3

'T.valueOf()'wouldn ' 정적 메소드'Number.valueOf()'가 있더라도 작동하지 않습니다. 당신은 단순히 이와 같은 제네릭 타입을 사용할 수 없습니다. –

답변

3

나는 TofuBeer와 100 % 동의합니다.

static <T extends Number> T sloppyParseNumber(String str,Class<T> clas) { 

    if (clas == null) throw new NullPointerException("clas is null"); 

    try { 

     if(clas.equals(Integer.class)) { 
      return (T) Integer.valueOf(str); 
     } 
     else if(clas.equals(Double.class)) { 
      return (T) Double.valueOf(str); 
     } 
     //so on 

    catch(NumberFormatException|NullPointerException ex) { 
     // force call with valid arguments 
     return sloppyParseNumber("0", clas); 
    } 

    throw new IllegalArgumentException("Invalid clas " + clas); 

} 

을하지만 순수 T에서, 당신은 런타임에 유형을 얻을 수 없습니다 그러나 경우에 당신이 시간을 위해 상세를 방지하고자,이 또한 수행해야합니다.

static String trimTo0(String str) { 
    if (str == null) return "0"; 
    str = str.trim(); 
    if (str.isEmpty()) return "0"; 
    return str; 
} 

사용법 :

+0

이것은 내가 질문에서 물어 본 것과 가장 가까운 접근법처럼 보입니다. 예외를 잡아 내고 올바른 서브 클래스를 반환하는 것을 선호합니다 (그래서'T'를 리턴하고'Class clas' 매개 변수를가집니다.). – hyde

+0

수정 됨. 감사. – Jatin

3

Java 제네릭은 컴파일 시간 확인 만 제공하며 컴파일 후 형식 정보가 거의 버려집니다. 따라서 T.valueOf 문은 Java에서 사용할 수 없습니다. 해결책은 이미 주석에서 언급 한 것처럼 장황한 방법으로 진행하는 것입니다. 또한 MyClass.<Double>sloppyParseNumber(value)을 수행하려는 이유가 있습니까? MyClass.sloppyParseDouble(value)이 아니므로 컴파일시에 유형을 지정 했으므로 사용할 수 없습니까?

+0

@hyde : 이해할 수 있는지 잘 모르겠습니다. "항상 같은 함수이고 타입을 지정하는 것은 아무 것도하지 않습니다"라고 말할 때, 타입을 지정하는 것이 아무런 효과가 없다고 생각하는 이유는 무엇입니까? 업데이트 된 예제에서'sloppyParseNumber'의 반환 유형은 무엇입니까? 전달 된 숫자가 BigDecimal, Double, Float, Integer 등으로 파싱되어야하는 방법을 어떻게 알 수 있습니까? –

+0

다시 시도해 보겠습니다 : MyClass의 목적. sloppyParseNumber'는 메소드가 Double 객체를 반환하도록 만들었지 만 실제로 Java 제네릭은 그런 식으로 작동하지 않으므로 메서드는 호출자가 지정한 유형을 알 수 없습니다. – hyde

2

정적 메서드는 형식이 기껏해야 Number이고 Number에는 valueOf 메서드가 없기 때문에 형식에 바인딩됩니다.

가장 쉬운 방법은 그냥 ... sloppyParseInt, sloppyParseFloat 등과 같은 정적 메소드를 만드는 것입니다

당신은 내가 그것을 좋아하지 확실하지, 같은 것을 할 수 있고, 아마에 개선 될 수있다 :

public class Main 
{ 
    private static final Map<Class<? extends Number>, NumberConverter> CONVERTERS; 

    static 
    { 
     CONVERTERS = new HashMap<>(); 
     CONVERTERS.put(Integer.class, new IntegerConverter()); 
    } 

    public static void main(String[] args) 
    { 
     Number valueA; 
     Number valueB; 

     valueA = CONVERTERS.get(Integer.class).convert("42"); 
     valueB = CONVERTERS.get(Integer.class).convert("Hello, World!"); 

     System.out.println(valueA); 
     System.out.println(valueB); 
    } 
} 

interface NumberConverter<T extends Number> 
{ 
    T convert(String str); 
} 

class IntegerConverter 
    implements NumberConverter<Integer> 
{ 
    @Override 
    public Integer convert(String str) 
    { 
     try 
     { 
      return Integer.valueOf(str); 
     } 
     catch (NumberFormatException ex) 
     { 
      return 0; 
     }  
    } 
} 
+2

더 나은 API는'NumberConvert.convert (Integer.class, string)'와 같은 호출을 가지고 내부적으로 세부 사항을 다루는 것이라고 생각합니다. –

0

그래서, 내가 다른 방법 결정이 질문의 방법보다 더 제한됩니다

String value = null; 
System.out println("Double value: " + Double.parseDouble(trimTo0(value))); 

주,이 무효로 변환하지 않고, 비 숫자 문자열은 "0"입니다. 이 작업을 완전히 수행하려면 두 가지 방법이 필요합니다. 하나는 소수점을 지원하고 다른 하나는 정수를 지원하는 것입니다.

0

이 시도 할 수 있습니다 :

여기
private <T> T convertToType(Class<T> clazz,String str) throws Exception { 
    return clazz.getConstructor(String.class).newInstance(str); 
} 

당신은 형식은 문자열 매개 변수가있는 생성자가 있어야 고려해야합니다.