Java에는 Integer, Float, Double, Long에 대한 변경 가능한 유형이 있습니까?


81

Integer와 같은 변경 가능한 버전을 사용하고 싶은 상황에 있습니다. 이 클래스 (아래)를 사용해야합니까? 아니면 Java에 내장 된 것이 있습니까?

http://www.java2s.com/Code/Java/Data-Type/Amutableintwrapper.htm


8
질문은 왜 이것을하기를 원합니까?
— helpermethod 2010

2
일부 경우 (예 : 게임, n칼로리가있는 음식 조각 저장, 고갈 / 추가 될 수 있음)의 경우 사용 이름을 따서 명명 된 클래스를 사용하는 것이 더 나을 수 있습니다 (예 : class FoodItem { int calories; }더 명확하고 메서드가 나중에 필요에 따라 추가 할 수.
— GKFX

7
Java 8 람다는 효과적인 최종 변수에서만 작동합니다. 이 제한을 해결하려면 변경 가능한 int가 필요합니다.
— 알렉스

메서드간에 전달해야하는 카운터가 필요할 수 있습니다. 를 전달하면 int한 메서드에서 증가하는 것처럼 작동하지 않고 값이 다른 메서드에 반영되지 않습니다.
— Adam Burley

답변:


51

아니요, Java에는 이러한 기능이 내장되어 있지 않습니다. 그 이유가 있습니다. 변경 가능한 유형을 사용하는 것은 쉽게 오용 될 수 있으므로 위험합니다. 또한 구현하기가 정말 쉽습니다. 예를 들어 commons-lang에는 MutableInt.


5
내 생각 엔 자바 개발자가 원하는 Integer가 int처럼 '동작'하는 것입니다. But..it 아직도 ... 나에게 어떻게 든 변경 가능한 옵션이 없습니다하는 이상한 것 같다
— rogerdpack

35
"변이 가능한 유형을 사용하는 것은 쉽게 오용 될 수 있기 때문에 위험합니다." 대부분의 것은 오용 될 수 있습니다. 불변 유형은 반사에 의해 변경 될 수 있지만 안전성이 중요한 경우에 존재합니다. 이러한 경우를 제외하면 사람들이 필요할 때 변경 가능한 유형을 사용하지 못하도록 막을 이유가 없습니다.
— GKFX

2
더 나은 방법으로, 불변 유형은 맵과 세트에서 혼동을 줄여줍니다. 변경 가능한 정수가 있고 키 역할을 한 값을 변경하면 컬렉션이 엉망이 될 것입니다. 그러나 Integer의 변경 가능한 구현이 필요한 경우 내부에 int 값이있는 클래스를 만드는 것보다 쉬운 것은 없습니다. 그리고 거기에서 창의력을 발휘할 수 있습니다. 예를 들어 Counter 또는 Countdown으로 만드십시오. 약간의 논리를 부여하십시오 (상향식으로 작동하는 Java EE에서 개발하지 않는 한).
— Vlasec 2014-08-05

확실히 오래된 질문이지만 누군가가 어떻게 오용 될 수 있는지 대답 할 수 있기를 바랍니다. 그것들을 사용하는 것이 왜 그렇게 위험한가요?
— 푹신한 로봇

@ user1175807 Vlasec이 언급했듯이 다른 곳에서 사용한 변수를 실수로 수정하면 이상한 버그가 발생합니다. 더 나쁜 것은 클라이언트의 코드와 함께 작동하는 프로그램을 작성하고 있다고 가정 해 봅시다. 변경 가능한 Integer 유형의 매개 변수가있는 메소드를 구현해야합니다. 이제 어떤 이유로 든 변경 가능한 Integer를 수정하면 클라이언트 프로그램에서도 변경 될 것입니다. 이는 완전히 예상치 못한 일이며 찾기 어려운 버그를 유발합니다.
— GregT

90

int[] mutable = {1};가변 래퍼 클래스에 대한 코드를 포함하는 것이 너무 번거 롭다면 항상 값을 배열로 래핑 할 수 있습니다.


30
똑똑하고 벌레처럼 못 생겼다.
— gvlasov

2
이것은 매우 영리하고 거의 공간을 차지하지 않습니다. 또한 AtomicInt로 수행되는 syching을 방지합니다.
— CompEng88

52

JDK 1.5 Java부터 이제 java.util.concurrent.atomic.AtomicInteger

스레드로부터 안전한 가변 정수입니다. 사용 예 :

final AtomicInteger value = new AtomicInteger(0);

그리고 나중에 :

value.incrementAndGet();

12
이 thead 안전은 많은 경우에 필요하지 않은 성능 비용으로 제공됩니다. 예를 들어 일반적인 사용 사례는 람다로 캡처 된 카운터를 증가시키는 것입니다. 원자를 사용하는 것은 과잉입니다.
— Minas Mina

12

다음은 변경 가능한 정수로 만든 작은 클래스입니다.

public class MutableInteger {
    private int value;
    public MutableInteger(int value) {
        this.value = value;
    }
    public void set(int value) {
        this.value = value;
    }
    public int intValue() {
        return value;
    }
}

이것을 다른 프리미티브로 쉽게 확장 할 수 있습니다. 물론 다른 사람들이 말하는 것처럼 신중하게 사용해야합니다.


1
IMHO가 가장 좋은 옵션은 원자 인터 거를 사용하는 것처럼 동시성에 대한 잘못된 단서를 제공하지 않는다는 것입니다. 그리고 배열, 정말로 나는 내 코드에서 그렇게 나쁜 일을하지 않을 것이다 ..;)
— Snicolas

당신이와 끝까지하지 않도록하는 대신 하나의 일반적인 래퍼 클래스를 제공하기 위해 좋은 아이디어가 될 수 MutableInteger, MutableDouble, MutableString등등을 대신 가지고 Mutable<Integer>, Mutable<Double>... (사용하는 메모리 오버 헤드 Integer이상은 int일반적으로 계정에 해당하지 않습니다. 그러나 당신은 얻을 하나, (당신이 당신의 정수는 여전히 서브 클래스에 필요 비교 또는 이와 유사한 것, 생각을하길 원한다면) 대부분의 경우를 처리 할 수있는 클래스를 사용할 준비가.
— Qw3ry

Number를 확장하는 것이 좋습니다 .
— Stijn de Witt

7

@Alexandre가 제안한 것처럼 nnnn []을 모든 기본 유형에 대한 변경 가능한 객체로 사용할 수 있습니다. java에는 AtomicInteger 및 AtomicLong도 있습니다.

IMHO int는 일반적으로 Integer보다 나은 선택이며 변경 가능합니다.

여러 개체가 필요한 이유에 대해 자세히 설명해 주시겠습니까? 동일한 작업을 수행하는 다른 방법이있을 수 있습니다.


8
int는 변경할 수 없습니다.
— mjaggard

7
int항상 변경 가능한 그 또한하지 않는 한final
— 피터 Lawrey

18
기본 유형이 변경 가능 하다고 말하는 것은 실제로 유효하지 않습니다 . 변경할 수 있지만 새 개체를 가리키면 최종 개체가 아닌 모든 개체 도 변경 될 수 있습니다 . 예를 들어 Integer a = 4;다음 a = 5;유효한 코드이지만, Integer변경할 수 없습니다.
— mjaggard

Integer인스턴스에 대한 참조가 있어도 변경 불가능 하다는 데 동의 하지만 다른 유형입니다.
— Peter Lawrey

1
int메서드에 전달하면 메서드가 값을 변경하고 새 값을 호출 메서드에 반영 할 방법이 없기 때문에 변경할 수 없습니다
— Adam Burley

5

AtomicInteger이미 언급되었습니다. mutable Double은 AtomicReference<Double>. 이미 언급 한 경고가 적용되고 잘못된 스타일이지만 때로는 이와 같은 코드가 있습니다.

double sum=0
for (Data data:someListGenerator())
  sum+=data.getValue()

기능적인 Java 8 스타일로 리팩토링하고 싶습니다. 코드가이 패턴을 따르지만 상당한 복잡성을 추가하는 경우 가장 현명한 변환 은 다음과 같습니다 .

AtomicReference<Double> sumref=new AtomicReference<>(0d);
someStreamGenerator().forEach(data->
  sumref.set(sumref.get().doubleValue()+data.getValue()));
double sum=sumref.get().doubleValue();

물론 이것은 적어도 의심스러운 스타일입니다. 그러나 나는 ResultSet컴퓨팅에 대한 뒤틀린 루프 와 부분적으로 세 가지 다른 정보를 누적 하는 상황에 두 번 이상 나 자신을 발견 했습니다. 이로 인해 코드를 적절한 기능 스타일로 변환하기가 정말 어렵습니다. 위의 패턴에 따라 누적 부분을 변환하는 것은 깨끗한 코드와 지나치게 단순화 된 리팩토링 사이의 합리적인 균형으로 보였습니다.


당신은 정말로 당신의 표현에 대해 생각해야합니다 : 람다를 사용하더라도, 당신의 예제는 부작용을 막기 때문에 작동 하지 않습니다 . 실제로 기능적으로 작성하면 변경 가능한 항목이 필요하지 않습니다 someStreamGenerator().mapToDouble(Data::getValue).sum(). 비록 세 가지 정보를 축적되는 들어,이 기능을 사용하여 방법 Stream.reduce나 Stream.collect. 모든 루프를 기능 코드 조각으로 리팩토링 할 이유는 없지만 그렇게하려면 끝까지 가야합니다.
— Tobias Liefke

내가 쓴대로 : 이것은 적절한 스타일 이 아니며 각각의 새로운 코드에 대해 이것을 사용해서는 안됩니다 . 그러나 15 년 넘게 진화 한 400.000 라인 이상의 코드를 리팩토링 할 때 진정한 기능적 구조로 적절하게 재 작성하는 것이 매우 어려울 수있는 구조를 발견하게됩니다 . 그런 다음 이러한 하이브리드 스타일로 다시 작성하는 것은 최소한 기본 구조를 조정함에 따라 합리적인 절충안이 될 수 있습니다. for그리고 foreach어떻게 든 주위를 나머지 코드를 정렬 할 수 있도록, 기능적으로 다시 작성하는 복잡한 프레임 워크의 일부가 될 수 있습니다.
— Dirk Hillbrecht

람다와 함수형 프로그래밍을 혼동하고 있습니다. 귀하의 예에서는 "기능적"으로 다시 작성하지 않았습니다. 가독성을 잃었지만 함수형 프로그래밍의 이점을 얻지 못한 경우 모든 것을 람다로 다시 작성하는 것이 요점은 무엇입니까? 왜 그러한 하이브리드를 사용하여 복잡한 프레임 워크의 모든 루프를 제거하려고 노력해야합니까?
— Tobias Liefke

코드에 특정 관용구가있는 1000 개의 장소가 있습니다. 관용구는 라이브러리 또는 모든 글로벌 구조에 의해 구동됩니다. 기능적 접근 방식과 람다를 기반으로 전역 구조를 새로운 구조로 바꿉니다. 1000 개의 장소 중 998 개를 깔끔하게 기능적인 스타일로 변환 할 수 있습니다. 나머지 2 개는 제대로 변환하기가 매우 어렵습니다. 그러한 경우, 나는 항상 그러한 하이브리드 구조로 새로운 스타일로 변환 할 것을 요구합니다. 그래야만 코드에 있던 오래된 전역 구조를 제거 할 수 있습니다. 완벽하지는 않지만 전반적인 코드 품질은 향상됩니다.
— Dirk Hillbrecht

2

org.omg.CORBA 패키지 (또는 필요한 클래스)를 가져올 수 있으며 그 안에 Holder 클래스를 사용할 수 있습니다.

예를 들어, 정수를 저장하는 필드가 public 인 "IntHolder"가있어이를 수정할 수있는 액세스 권한을 부여합니다.

public static void triple(IntHolder x){
    x.value = 3 * x.value;
}

IntHolder mutableInt = new IntHolder(10);
triple(mutableInt);     
System.out.println(mutableInt.value);

또한 "LongHolder"및 "DoubleHolder"및 사용할 수있는 기타 항목도 많이 있습니다. 주의해서 사용하십시오.

여기에 대한 API가 있습니다 : https://docs.oracle.com/javase/7/docs/api/org/omg/CORBA/package-summary.html


2
문제를 해결하는 매우 현명한 방법이지만 Java9가 나오면 아마도 이것을 사용하고 싶지 않을 것입니다-int 홀더를 위해 전체 CORBA 모듈을 가져옵니다.
— Agoston Horvath 2016
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.