2010-08-23 5 views
9

일반적으로 임의의 숫자 유형을 0으로 만들려면 어떻게해야합니까?제네릭 Number 서브 클래스의 제로 값을 생성하십시오.

다음은 장난감의 예입니다. 널 번호를 0으로 변환하는 함수입니다.

static <T extends Number> T zeroIfNull(T value) { 
    return value == null ? 0 : value; 
} 

문자 그대로 제로 유형 int의 때문이 컴파일되지 않습니다, 나는 그 T를 입력 변환해야합니다.

이렇게 할 수 있습니까?

답변

2

Number 클래스에는 0이 언급되지 않았습니다. 이 작업을 수행해야하고, 내가 null의를 피하는 것이 좋습니다 경우, 아마도 :

public static <T> T coalesce(T a, T b) { 
    return a==null ? b : a; 
} 
당신은 또한 당신의 코드를 이해 기능 수를 처리하기위한 일반적인 인터페이스를 만들 수

:

interface NumberOps<T extends Number> { 
    T zeroIfNull(T value); 
} 
+0

이것은 가장 우아한 방법입니다. Java가 통합 연산자를 사용하기를 바랍니다. 어쩌면 그냥 C#을 사용해야합니다 :) –

3

이렇게 할 수 있습니까?
아니요. 한 가지는 value가 null 일 때 반환 할 Number 구현을 메소드가 어떻게 알 수 있습니까?

+0

네, 맞아요. 타입 지우기가 다시 물었다. –

+0

@Bennett 유형 삭제에 관한 것만이 아닙니다. _Number num = null; _을 선언하고 _zeroIfNull (num) _을 호출하면 형식 지우기가 없어도 혼동을 일으킬 수 있습니다. –

+0

서명을 약간 변형하면 T zeroIfNull (T 값, Class clazz) 형식을 지울 수 있습니다. T가 표준 수업 중 하나가 아닌 경우에도해야 할 일을 결정해야합니다. (E.G. Prime은 소수 2, ...를 모델로하고 0 값을 갖지 않습니다 .0 zeroIfNull (null, Prime.class)는 무엇을합니까?) – emory

1

시도 :

static <T extends Number> T zeroIfNull(T value, Class<T> clazz) {...} 

및 사용했을 때 :

return value == null ? (T)Integer.valueOf(0) : value; 
+0

유일한 문제는 항상 정수 유형이 0을 반환한다는 것입니다. (또한 자동 저장 때문에 "Integer.valueOf (0)"을 "0"으로 바꿀 수 있습니다. –

+0

정수는 종류의 일종입니다. 반환 값은 이며, null (특정 유형 없음)이 전달 되었기 때문에 Integer는 정상입니다. –

+0

나는 이것을 시도해 보았고 반환 값이'toString()'을 사용하여 String으로 변환되기 때문에 내 경우에는 작동 할 수도있다. 그러나 BigInteger 값으로 호출 한 다음'abs() '를 호출하면 문제가 생길 수 있습니다. –

-1

하지 않는 것이 우아하지만 가장 유사한 경우에 생각, 그것은 우리가 무엇을 할 수

BigDecimal v = zeroIfNull(orignalVal, BigDecimal.class); 
+0

하지만이 방법을 어떻게 구현합니까? –

-1
import java . math . * ; 

class Numbers 
{ 
    public static < T extends Number > T zeroIfNull (T number , Class<T> clazz) throws IllegalArgumentException 
    { 
    if (clazz == Integer . class) 
     { 
     return zeroIfNull (number , clazz , 0) ; 
     } 
    else if (clazz == Double . class) 
     { 
     return zeroIfNull (number , clazz , 0) ; 
     } 
    else if (clazz == BigInteger . class) 
     { 
     return zeroIfNull (number , clazz , BigInteger . ZERO) ; 
     } 
    // add a whole bunch more if statements 
    throw new IllegalArgumentException ("Unexpected Number Class " + clazz . getName () + " with possibly undefined zero value.") ; 
    } 

    private static < T extends Number > T zeroIfNull (T number , Class<T> clazz , Object zero) 
    { 
    if (number == null) 
     { 
     return (clazz . cast (zero)) ; 
     } 
    else 
     { 
     return (number) ; 
     } 
    } 
} 
+0

흠. 나는 적어도 두 번째 방법에서 'Object zero'가 'T zero'여야한다고 생각한다. –

+0

@Bennett 그러면 컴파일되지 않습니다. 첫 번째 방법으로 캐스팅을 추가해야합니다. 두 번째 메소드를 비공개로 만들고 첫 번째 메소드에서만 호출하면 0 값은 T 유형이되고 캐스트는 문제가되지 않습니다. – emory

+0

오, 물론 당신은 0을 던져야 할 것입니다. 제가 말했듯이, 이것은 명확성을 돕습니다. –

-1

다음은 첫 번째 대답을 개선 한 것입니다.

import java . math . * ; 
import java . util . * ; 

class Numbers 
{ 
    private static final Map<Class<? extends Number>,Object> zeroes = new HashMap<Class<? extends Number>,Object> () ; 

    static 
    { 
     zeroes . put (Integer . class , new Integer (0)) ; 
     zeroes . put (Double . class , new Double (0.0)) ; 
     zeroes . put (BigInteger . class , BigInteger . ZERO) ; 
     // fill it up with all supported classes 
    } 

    public static < T extends Number > T zeroIfNull (T number , Class<T> clazz) throws IllegalArgumentException 
    { 
    if (number == null) // return zero (if we know what zero is) 
     { 
     if (zeroes . containsKey (clazz)) 
      { 
      return (clazz . cast (zeroes . get (clazz))) ; 
      } 
     throw new IllegalArgumentException ("Unexpected Number Class " + clazz . getName () + " with undefined zero value.") ; 
     } 
    return number ; 
    } 
} 
+0

네, 이런 종류의 문제가 제가 질문 한 이유입니다. 나는 더 좋은 방법이 있기를 바랐다. –

1

이를 오래된 질문은 그러나 얼마 동안이 문제를 고민 한 후 나는 다른 사람들에게 관심을 가질 수있는 해결책을했다 : 이것은 잘 작동

@SuppressWarnings("unchecked") 
public static <T extends Number> T getZero() { 
    return (T)((Integer)0); 
} 

오래는 산술 연산에 관해서는, 예를 들어, 일부 알려진 유형으로 인스턴스를 변환 할 수 있습니다으로 : 그것은의 인스턴스의 경우는 변수의 유형을 중요하지 않습니다 이러한 상황에서

double getSquareRoot(T x) { 
    return Math.sqrt(x.doubleValue()); 
} 

번호는 항상 두 배가 될 수 있습니다.

관련 문제