programing

Java에서 안전하게 int에 캐스팅

bestcode 2022. 8. 27. 09:36
반응형

Java에서 안전하게 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오버플로우일 경우.

참조:

Java 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)

다음과 같은 int 값을 반환합니다.value,가능하면.

파라미터: value- 의 범위 내의 임의의 값int유형

반품:int같은 값value

던지기: IllegalArgumentException- 만약value보다 크다Integer.MAX_VALUE이하Integer.MIN_VALUE

덧붙여서, 당신은 그 일을 할 필요가 없다.safeLongToInt물론 광범위한 리팩터링 없이 기능을 변경하기 위해 래퍼를 그대로 두는 것이 바람직하지 마십시오.

Big Decimal의 경우:

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);
}

이건 해결책이 아니야!

첫 번째 접근법은 다음과 같습니다.

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

하지만 그것은 단지 장황한 것을 int에 던져넣을 뿐이고 잠재적으로 새로운 것을 만들어 낼 수 있다.Long인스턴스 또는 롱 풀에서 인스턴스를 검색합니다.


결점

  1. Long.valueOf신규 생성Long번호가 범위 내에 없는 경우 인스턴스Long의 풀 범위 [-128, 127]

  2. intValue구현은 다음 작업만 수행합니다.

    return (int)value;
    

그래서 이건 그냥 연기하는 것보다 더 나쁜 것으로 여겨질 수 있어long로.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클라이언트 코드에 관한 한 잘못된 예외는 거의 확실합니다.

Java 정수형은 부호 있는 것으로 표시됩니다.2와32 2 사이의 입력31(또는31 -2와 -232)을 사용하면 캐스팅은 성공하지만 검정은 실패합니다.

해야 할 것은 '고비트'의가 '고비트'인지 입니다.long모두 동일합니다.

public static final long LONG_HIGH_BITS = 0xFFFFFFFF80000000L;
public static int safeLongToInt(long l) {
    if ((l & LONG_HIGH_BITS) == 0 || (l & LONG_HIGH_BITS) == LONG_HIGH_BITS) {
        return (int) l;
    } else {
        throw new IllegalArgumentException("...");
    }
}
(int) (longType + 0)

단, Long은 최대값을 초과할 수 없습니다.

또 하나의 솔루션은 다음과 같습니다.

public int longToInt(Long longVariable)
{
    try { 
            return Integer.valueOf(longVariable.toString()); 
        } catch(IllegalArgumentException e) { 
               Log.e(e.printstackstrace()); 
        }
}

클라이언트가 POST를 실행하고 서버 DB가 Integress만 인식하는 경우 Long이 있는 경우 이 방법을 사용해 보았습니다.

언급URL : https://stackoverflow.com/questions/1590831/safely-casting-long-to-int-in-java

반응형