[java] Java에서 long to int로 안전하게 캐스팅

에서 주조 있는지 확인하기 위해 자바에서 가장 관용적 인 방법은 무엇 long에이 int정보를 잃지 않는다는?

이것은 내 현재 구현입니다.

public static int safeLongToInt(long l) {
    int i = (int)l;
    if ((long)i != l) {
        throw new IllegalArgumentException(l + " cannot be cast to int without changing its value.");
    }
    return i;
}



답변

이를 위해 Java 8 에 새로운 방법이 추가되었습니다 .

import static java.lang.Math.toIntExact;

long foo = 10L;
int bar = toIntExact(foo);

ArithmeticException오버플 로 가 발생 하면 던질 것 입니다.

보다: Math.toIntExact(long)

몇 가지 다른 오버 플로우 안전한 방법은 그들로 끝 자바 8에 추가 된 정확한 .

예 :

  • Math.incrementExact(long)
  • Math.subtractExact(long, long)
  • Math.decrementExact(long)
  • Math.negateExact(long),
  • Math.subtractExact(int, int)

답변

나는 다음과 같이 간단하게 할 것이라고 생각합니다.

public static int safeLongToInt(long l) {
    if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
        throw new IllegalArgumentException
            (l + " cannot be cast to int without changing its value.");
    }
    return (int) l;
}

반복 캐스팅보다 의도를 더 명확하게 표현한다고 생각하지만 다소 주관적입니다.

잠재적 관심에 주목하십시오-C #에서는 다음과 같습니다.

return checked ((int) l);


답변

Google Guava의 Ints 클래스를 사용하면 메소드를 다음과 같이 변경할 수 있습니다.

public static int safeLongToInt(long l) {
    return Ints.checkedCast(l);
}

연결된 문서에서 :

점검

public static int checkedCast(long value)

value가능한 경우와 동일한 int 값을 반환 합니다.

매개 변수 :
valueint유형 범위의 모든 값

반환 값 :int 값 같value

예외 :
IllegalArgumentExceptionvalue이보다 크 Integer.MAX_VALUE거나 작은 경우Integer.MIN_VALUE

또한 safeLongToInt광범위한 리팩토링없이 기능을 변경하기 위해 래퍼를 남겨 두지 않는 한 래퍼 가 필요하지 않습니다 .


답변

BigDecimal로 :

long aLong = ...;
int anInt = new BigDecimal(aLong).intValueExact(); // throws ArithmeticException
                                                   // if outside bounds


답변

여기에 필요한 것보다 큰 경우 가치에 신경 쓰지 않는 경우 해결책이 있습니다.)

public static int safeLongToInt(long l) {
    return (int) Math.max(Math.min(Integer.MAX_VALUE, l), Integer.MIN_VALUE);
}


답변

DONT : 이것은 해결책이 아닙니다!

내 첫 번째 접근 방식은 다음과 같습니다.

public int longToInt(long theLongOne) {
  return Long.valueOf(theLongOne).intValue();
}

그러나 그것은 단지 long을 int로 캐스팅하여 잠재적으로 새로운 Long인스턴스를 생성 하거나 Long 풀에서 검색 할 수 있습니다.


단점

  1. Long.valueOfLong숫자가 Long풀 범위 [-128, 127] 내에없는 경우 새 인스턴스를 만듭니다 .

  2. intValue구현은 다음을 수행합니다.

    return (int)value;

따라서 이것은 longto에 캐스팅하는 것보다 더 나쁜 것으로 간주 될 수 있습니다 int.


답변

값을 캐스팅하면 값이 변경되었는지 확인하는 확실한 방법은 캐스팅하고 결과를 확인하는 것입니다. 그러나 비교할 때 불필요한 캐스트를 제거합니다. 나는 또한 너무 한 문자 변수 이름에 예리한 (예외 아니에요 x하고 y있지만 때 평균 행과 열 (때로는 각각)).

public static int intValue(long value) {
    int valueInt = (int)value;
    if (valueInt != value) {
        throw new IllegalArgumentException(
            "The long value "+value+" is not within range of the int type"
        );
    }
    return valueInt;
}

그러나 실제로 가능한 경우이 변환을 피하고 싶습니다. 분명히 가능하지는 않지만 IllegalArgumentException클라이언트 코드와 관련하여 예외가 발생하는 것은 거의 확실합니다.