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 DoubleAtomicReference<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.reduceStream.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.