Jestem w sytuacji, w której chcę używać mutowalnych wersji rzeczy, takich jak Integer. Czy muszę używać tych klas (poniżej), czy też Java ma coś wbudowanego?
http://www.java2s.com/Code/Java/Data-Type/Amutableintwrapper.htm
Jestem w sytuacji, w której chcę używać mutowalnych wersji rzeczy, takich jak Integer. Czy muszę używać tych klas (poniżej), czy też Java ma coś wbudowanego?
http://www.java2s.com/Code/Java/Data-Type/Amutableintwrapper.htm
n
kalorie, który może zostać zubożony / dodany), może być lepiej użyć klasy nazwanej na podstawie użycia (np. class FoodItem { int calories; }
Ponieważ jest ona bardziej przejrzysta, a metody mogą być dodane w razie potrzeby później
int
nie działa tak, jakby było inkrementowane w jednej metodzie, wtedy wartość nie zostanie odzwierciedlona w drugiej metodzie.
Odpowiedzi:
Nie, Java nie ma ich wbudowanych. Nie bez powodu. Używanie typów zmiennych jest niebezpieczne, ponieważ można je łatwo nadużywać. Dodatkowo jest to naprawdę łatwe do wdrożenia. Na przykład commons-lang ma rozszerzenie MutableInt
.
Zawsze możesz zawinąć wartość w tablicę, tak jak int[] mutable = {1};
wtedy, gdy dołączenie kodu dla mutowalnej klasy opakowania jest zbyt kłopotliwe.
Od JDK 1.5 java ma teraz java.util.concurrent.atomic.AtomicInteger
To jest zmienna liczba całkowita bezpieczna dla wątków, przykład użycia:
final AtomicInteger value = new AtomicInteger(0);
potem później:
value.incrementAndGet();
Oto mała klasa, którą utworzyłem dla mutowalnej liczby całkowitej:
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;
}
}
Możesz łatwo rozszerzyć to na dowolny inny prymityw. Oczywiście, jak wszyscy mówią, powinieneś używać go ostrożnie.
MutableInteger
, MutableDouble
, MutableString
itd., Ale zamiast mieć Mutable<Integer>
, Mutable<Double>
... Szczytowy pamięci (z użyciem Integer
ponad int
zazwyczaj nie wchodzą pod uwagę. Ale otrzymujesz jedną, gotową do użycia klasę, która może obsłużyć większość przypadków (jeśli chcesz, aby twoja liczba całkowita była porównywalna lub podobna, nadal musisz
Możesz użyć nnnn [] jako zmiennego obiektu dla dowolnego typu pierwotnego, jak sugeruje @Alexandre, java ma również AtomicInteger i AtomicLong.
IMHO int jest zwykle lepszym wyborem niż Integer i jest zmienny.
Czy możesz dowiedzieć się więcej o tym, dlaczego potrzebujesz wielu obiektów, być może istnieje inny sposób na osiągnięcie tego samego.
int
jest zawsze zmienna, chyba że jej równieżfinal
Integer a = 4;
wtedy a = 5;
jest prawidłowy kod, ale Integer
nie jest zmienny.
Integer
instancje nie są modyfikowalne, nawet jeśli istnieją odniesienia do nich, ale to inny typ.
int
Nie jest zmienny, ponieważ jeśli przekazać ją do metody, nie ma sposobu na sposób zmienić swoją wartość i mają nową wartość odzwierciedlenie w sposobie dzwoniącej
AtomicInteger
zostało już wspomniane. Zmienne Double
s można emulować za pomocą AtomicReference<Double>
. Wspomniane już ostrzeżenia obowiązują i jest to zły styl, ale czasami masz taki kod
double sum=0
for (Data data:someListGenerator())
sum+=data.getValue()
i chcesz go zrefaktoryzować w funkcjonalnym stylu Java 8. Jeśli kod jest zgodny z tym wzorcem, ale dodaje mu znaczną złożoność, najbardziej sensowna może być konwersja
AtomicReference<Double> sumref=new AtomicReference<>(0d);
someStreamGenerator().forEach(data->
sumref.set(sumref.get().doubleValue()+data.getValue()));
double sum=sumref.get().doubleValue();
Oczywiście jest to co najmniej wątpliwy styl. Ale wielokrotnie znajdowałem się w sytuacji, w której pętla była zakręcona na ResultSet
komputerze i częściowo gromadziła z niej trzy różne informacje. To sprawia, że naprawdę trudno jest przekształcić kod w odpowiedni styl funkcjonalny. Konwersja kumulowanych części zgodnie z powyższym wzorem wydawała mi się rozsądnym kompromisem między czystym kodem a nadmiernie uproszczoną refaktoryzacją.
someStreamGenerator().mapToDouble(Data::getValue).sum()
. Nawet w przypadku gromadzenia trzech różnych informacji istnieje funkcjonalny sposób za pomocą Stream.reduce
lub Stream.collect
. Nie widzę powodu, aby refaktoryzować każdą pętlę do funkcjonalnego fragmentu kodu, ale jeśli chcesz iść w ten sposób, powinieneś to zrobić do końca.
for
i foreach
mogą być częściami złożonych frameworków, które zostały przepisane funkcjonalnie, więc musisz jakoś dopasować resztę kodu do nich.
Możesz zaimportować pakiet org.omg.CORBA (lub po prostu potrzebną Ci klasę) i użyć w nim klas Holder.
Na przykład ma „IntHolder”, gdzie pole, w którym przechowuje liczbę całkowitą, jest publiczne, co daje dostęp do jej modyfikacji.
public static void triple(IntHolder x){
x.value = 3 * x.value;
}
IntHolder mutableInt = new IntHolder(10);
triple(mutableInt);
System.out.println(mutableInt.value);
Posiada również „LongHolder” i „DoubleHolder” oraz mnóstwo innych, których możesz używać. Używaj ostrożnie.
Oto jego interfejs API: https://docs.oracle.com/javase/7/docs/api/org/omg/CORBA/package-summary.html