Wynik operacji binarnej jest konwertowany na typ lewej zmiennej ... a wynik konwersji jest zapisywany w zmiennej.
Na przykład:
char x = 1, y = 2;
x = x + y; // compile error: "possible loss of precision (found int, required char)"
x = (char)(x + y); // explicit cast back to char; OK
x += y; // compound operation-assignment; also OK
Jednym ze sposobów, aby dowiedzieć się, jaki jest typ wyniku, jest rzutowanie go na obiekt i zapytanie, jaka to klasa:
System.out.println(((Object)('a' + 'b')).getClass());
// outputs: class java.lang.Integer
Jeśli interesuje Cię wydajność, zwróć uwagę, że kod bajtowy Java nie ma nawet dedykowanych instrukcji arytmetycznych z mniejszymi typami danych. Na przykład w przypadku dodawania, istnieją instrukcje iadd(na int), ladd(na wyroby długie), fadd(dla pływaków), dadd(dla podwójnej), i to wszystko. Aby przeprowadzić symulację x += yz mniejszymi typami, kompilator użyje, iadda następnie wyzeruje górne bajty int, używając instrukcji takiej jak i2c(„int to char”). Jeśli natywny procesor ma dedykowane instrukcje dla danych 1-bajtowych lub 2-bajtowych, to maszyna wirtualna Java musi je zoptymalizować w czasie wykonywania.
Jeśli chcesz konkatenować znaki jako ciąg znaków, zamiast interpretować je jako typ liczbowy, istnieje wiele sposobów, aby to zrobić. Najłatwiej jest dodać pusty ciąg do wyrażenia, ponieważ dodanie znaku i ciągu daje w wyniku ciąg. Wszystkie te wyrażenia powodują powstanie ciągu "ab":
'a' + "" + 'b'
"" + 'a' + 'b'(to działa, ponieważ "" + 'a'jest oceniane jako pierwsze; gdyby ""zamiast tego były na końcu, otrzymasz "195")
new String(new char[] { 'a', 'b' })
new StringBuilder().append('a').append('b').toString()
Chociaż cjest to typ char, można go podać bez błędów w odpowiednich konstruktorach, a wszystkie powyższe instrukcje są traktowane jako prawidłowe instrukcje. Dają odpowiednio następujące wyniki.
charjest prymitywnym liczbowym typem całkowitym i jako taki podlega wszystkim regułom tych bestii, łącznie z konwersjami i promocjami. Będziesz chciał poczytać o tym, a JLS jest jednym z najlepszych źródeł tego: Konwersje i promocje . W szczególności przeczytaj krótki fragment „5.1.2 Poszerzanie pierwotnej konwersji”.
Dziwię się, że nie otrzymałeś ostrzeżenia kompilatora w drugim przypadku o możliwej utracie precyzji z powodu zawężenia.
Hot Licks
@eboix: napisałeś "kompilator automatycznie rzutuje na char lub int" [sic] ... Co nie jest poprawne, ponieważ int nie jest "rzutowany" na int, a przejście z int do char nie jest wywoływane „obsada”, ale „zawężająca prymitywna konwersja”; )
TacticalCoder
Tak. Tego też się spodziewałem. Właściwie napisałem część mojej odpowiedzi na ten temat przed utworzeniem programu, ale potem usunąłem ją, gdy zobaczyłem, że nie otrzymałem żadnych ostrzeżeń ani błędów.
eboix
@eboix: eh eh:) Zmieniłbym to, ale nie mam jeszcze 2 000 punktów reputacji, stąd mój komentarz zamiast edycji; )
TacticalCoder
Jeśli chcesz, @ user988052, mogę zmienić to z powrotem na to, co było i możesz to edytować, zdobywając punkty. Nadal możesz ją edytować, jeśli masz mniej niż 2000 punktów reputacji. Jedyną rzeczą jest to, że osoba, która opublikowała wpis, musi zaakceptować edycję. Zmienię go z powrotem teraz, abyś mógł zdobyć dwa punkty, które są twoje.
eboix
1
Zgodnie z regułami promocji binarnej , jeśli żaden z operandów nie jest podwójny, zmiennoprzecinkowy ani długi, oba są promowane do int. Jednak zdecydowanie odradzam traktowanie typu char jako liczbowego, bo to mija się z celem.
Używanie charjako wartości liczbowej jest całkowicie zgodne z jego celem, dlatego JLS poświęca tak wiele słownictwa na takie użycie.
Lew Bloch
1
Chociaż masz już poprawną odpowiedź (przywoływaną w JLS), oto fragment kodu, aby sprawdzić, czy otrzymujesz odpowiedź intpodczas dodawania dwóch chars.
publicclassCharAdditionTest{
publicstaticvoidmain(String args[]){
char a = 'a';
char b = 'b';
Object obj = a + b;
System.out.println(obj.getClass().getName());
}
}
To nie jest przekonująca weryfikacja, ponieważ wrzuciłeś do miksu konwersję bokserską. Rodzaje inti Integerto nie to samo. Weryfikacja bardziej przekonujące jest próba przypisania a + bdo intzmiennej lub charzmiennej. Ten ostatni powoduje błąd kompilacji, który mówi, że w efekcie „nie można przypisać an intdo a char”.
Stephen C
0
charjest reprezentowany jako Unicodewartości i gdzie wartości Unicode są reprezentowane \uprzez Hexadecimalwartości.
Jak każda operacja arytmetyczna na charwartościach promowanych do int, więc wynik 'a' + 'b'jest obliczany jako
1.) Zastosuj Unicodewartości przy odpowiednim charużyciuUnicode Table
Do Twojej wiadomości, Moja szczegółowa odpowiedź na powyższy komentarz została usunięta przez mody, które wyjaśniały powód migracji mojej odpowiedzi z usuniętego posta. jeśli moja odpowiedź została usunięta, aby ukryć błędy moderacji SO, to czy możesz przynajmniej usunąć powyższy komentarz lub w jakiś sposób wskazać publiczność, abym nie musiał pisać kolejnego komentarza? pytania do modów SO
Pavneet_Singh
Podtrzymuję swój komentarz. Tak jak ci odpowiedziałem ... ale potem usunąłem ... powód, dla którego zamieściłeś to pytanie tutaj, nie zmienia faktu, że jest ono w 95% nie na temat pytania i 5% powtórzenia wcześniejszych odpowiedzi. Jeśli chcesz zachować wyniki zmarnowanego wysiłku, lepiej byłoby zapisać je na dysku twardym. Lub znajdź inne pytanie, dla którego jest to istotne.
Stephen C
Jeśli masz problemy z moderatorami, zgłoś je na meta.stackoverflow.com. I przedstaw dowody. Jedyne, co próbuję tutaj zrobić, to posprzątać >> to << Q&A.
Stephen C
Rozumiem twój pogląd, ale nie mogę zrozumieć faktu ignorowania szczegółów konwersji Unicode z przykładami, jako dodatkowej wartości, która może pomóc niektórym czytelnikom, więc chciałbym zachować tę odpowiedź (rozumiem, że nie jest to dla ciebie przydatne i wydaje się nie- temat). Unikam meta i podobnych miejsc, ponieważ nie jest łatwo robić takie rzeczy bez zasilania i wsparcia, co zajmuje dużo czasu, wysiłku. Wolę zachować wewnętrzny spokój, Panie.
Pavneet_Singh
0
Chociaż odpowiedź Boanna jest poprawna, istnieje komplikacja, która dotyczy przypadku wyrażeń stałych , które pojawiają się w kontekstach przypisań .
Rozważ następujące przykłady:
char x = 'a' + 'b'; // OKchar y = 'a';
char z = y + 'b'; // Compilation error
Co się dzieje? Mają na myśli to samo, prawda? I dlaczego legalne jest przypisanie a intdochar w pierwszym przykładzie ?
Gdy stałe wyrażenie pojawia się w kontekście przypisania, kompilator Java oblicza wartość wyrażenia i sprawdza, czy mieści się ona w zakresie typu, do którego przypisujesz. Jeśli tak, jest stosowana niejawna konwersja pierwotna zawężająca .
W pierwszym przykładzie 'a' + 'b'jest wyrażeniem stałym, a jego wartość zmieści się w a char, więc kompilator umożliwia niejawne zawężenie intwyniku wyrażenia do a char.
W drugim przykładzie yjest zmienną, więc y + 'b'NIE jest wyrażeniem stałym. Więc nawet jeśli Blind Freddy widzi, że wartość będzie pasować, kompilator NIE zezwala na żadne niejawne zawężenie, a ty otrzymujesz błąd kompilacji mówiący, że intnie można przypisać pliku char.
Istnieją inne zastrzeżenia co do tego, kiedy w tym kontekście dozwolona jest niejawna, zawężająca konwersja pierwotna ; szczegółowe informacje znajdują się w JLS 5.2 i JLS 15.28 .
Ten ostatni szczegółowo wyjaśnia wymagania dotyczące stałej ekspresji . Może nie być tym, co myślisz. (Na przykład samo zadeklarowanie yjako finalnie pomaga).
char
wówczas wartość'a' + 'b'
nie byłoby195
jednak'Ã'
Odpowiedzi:
Wynikiem dodania znaków, skrótów lub bajtów Java jest int :
Specyfikacja języka Java w promocji binarnych liczb liczbowych :
Ale zwróć uwagę, co mówi o operatorach przypisania złożonych (takich jak + =) :
Na przykład:
char x = 1, y = 2; x = x + y; // compile error: "possible loss of precision (found int, required char)" x = (char)(x + y); // explicit cast back to char; OK x += y; // compound operation-assignment; also OK
Jednym ze sposobów, aby dowiedzieć się, jaki jest typ wyniku, jest rzutowanie go na obiekt i zapytanie, jaka to klasa:
System.out.println(((Object)('a' + 'b')).getClass()); // outputs: class java.lang.Integer
Jeśli interesuje Cię wydajność, zwróć uwagę, że kod bajtowy Java nie ma nawet dedykowanych instrukcji arytmetycznych z mniejszymi typami danych. Na przykład w przypadku dodawania, istnieją instrukcje
iadd
(na int),ladd
(na wyroby długie),fadd
(dla pływaków),dadd
(dla podwójnej), i to wszystko. Aby przeprowadzić symulacjęx += y
z mniejszymi typami, kompilator użyje,iadd
a następnie wyzeruje górne bajty int, używając instrukcji takiej jaki2c
(„int to char”). Jeśli natywny procesor ma dedykowane instrukcje dla danych 1-bajtowych lub 2-bajtowych, to maszyna wirtualna Java musi je zoptymalizować w czasie wykonywania.Jeśli chcesz konkatenować znaki jako ciąg znaków, zamiast interpretować je jako typ liczbowy, istnieje wiele sposobów, aby to zrobić. Najłatwiej jest dodać pusty ciąg do wyrażenia, ponieważ dodanie znaku i ciągu daje w wyniku ciąg. Wszystkie te wyrażenia powodują powstanie ciągu
"ab"
:'a' + "" + 'b'
"" + 'a' + 'b'
(to działa, ponieważ"" + 'a'
jest oceniane jako pierwsze; gdyby""
zamiast tego były na końcu, otrzymasz"195"
)new String(new char[] { 'a', 'b' })
new StringBuilder().append('a').append('b').toString()
String.format("%c%c", 'a', 'b')
źródło
Binarne operacje arytmetyczne na
char
ibyte
(ishort
) promują doint
- JLS 5.6.2.źródło
Możesz chcieć nauczyć się następujących wyrażeń na temat
char
.char c='A'; int i=c+1; System.out.println("i = "+i);
Jest to całkowicie poprawne w Javie i zwraca
66
odpowiednią wartość znaku (Unicode)c+1
.String temp=""; temp+=c; System.out.println("temp = "+temp);
Jest to zbyt poprawne w Javie, a zmienna typu String
temp
automatycznie akceptujec
typ char i generujetemp=A
na konsoli.Wszystkie poniższe instrukcje obowiązują również w Javie!
Integer intType=new Integer(c); System.out.println("intType = "+intType); Double doubleType=new Double(c); System.out.println("doubleType = "+doubleType); Float floatType=new Float(c); System.out.println("floatType = "+floatType); BigDecimal decimalType=new BigDecimal(c); System.out.println("decimalType = "+decimalType); Long longType=new Long(c); System.out.println("longType = "+longType);
Chociaż
c
jest to typchar
, można go podać bez błędów w odpowiednich konstruktorach, a wszystkie powyższe instrukcje są traktowane jako prawidłowe instrukcje. Dają odpowiednio następujące wyniki.intType = 65 doubleType = 65.0 floatType = 65.0 decimalType = 65 longType =65
char
jest prymitywnym liczbowym typem całkowitym i jako taki podlega wszystkim regułom tych bestii, łącznie z konwersjami i promocjami. Będziesz chciał poczytać o tym, a JLS jest jednym z najlepszych źródeł tego: Konwersje i promocje . W szczególności przeczytaj krótki fragment „5.1.2 Poszerzanie pierwotnej konwersji”.źródło
Kompilator Java może zinterpretować to jako jeden z nich.
Sprawdź to pisząc program i szukając błędów kompilatora:
public static void main(String[] args) { int result1 = 'a' + 'b'; char result2 = 'a' + 'b'; }
Jeśli jest to znak, w pierwszej linii pojawi się błąd, aw drugiej nie. Jeśli jest to int, stanie się odwrotnie.
Skompilowałem i nie otrzymałem ..... ŻADNYCH BŁĘDÓW. Tak więc Java akceptuje oba.
Jednak gdy je wydrukowałem, otrzymałem:
Dzieje się tak, gdy:
char result2 = 'a' + 'b'
wykonywana jest niejawna konwersja („pierwotna konwersja zawężająca” z int na char ).
źródło
Zgodnie z regułami promocji binarnej , jeśli żaden z operandów nie jest podwójny, zmiennoprzecinkowy ani długi, oba są promowane do int. Jednak zdecydowanie odradzam traktowanie typu char jako liczbowego, bo to mija się z celem.
źródło
char
jako wartości liczbowej jest całkowicie zgodne z jego celem, dlatego JLS poświęca tak wiele słownictwa na takie użycie.Chociaż masz już poprawną odpowiedź (przywoływaną w JLS), oto fragment kodu, aby sprawdzić, czy otrzymujesz odpowiedź
int
podczas dodawania dwóchchar
s.public class CharAdditionTest { public static void main(String args[]) { char a = 'a'; char b = 'b'; Object obj = a + b; System.out.println(obj.getClass().getName()); } }
Wynik jest
źródło
int
iInteger
to nie to samo. Weryfikacja bardziej przekonujące jest próba przypisaniaa + b
doint
zmiennej lubchar
zmiennej. Ten ostatni powoduje błąd kompilacji, który mówi, że w efekcie „nie można przypisać anint
do achar
”.char
jest reprezentowany jakoUnicode
wartości i gdzie wartości Unicode są reprezentowane\u
przezHexadecimal
wartości.Jak każda operacja arytmetyczna na
char
wartościach promowanych doint
, więc wynik'a' + 'b'
jest obliczany jako1.) Zastosuj
Unicode
wartości przy odpowiednimchar
użyciuUnicode Table
2.) Zastosuj konwersję Szesnastkowy na Dziesiętny, a następnie wykonaj operację na
Decimal
wartościach.char Unicode Decimal a 0061 97 b 0062 98 + 195
Unicode To Decimal Converter
Przykład
0061
0062
W związku z tym
97 + 98 = 195
Przykład 2
char Unicode Decimal Ջ 054b 1355 À 00c0 192 -------- 1547 + 1163 - 7 / 260160 * 11 %
źródło
Chociaż odpowiedź Boanna jest poprawna, istnieje komplikacja, która dotyczy przypadku wyrażeń stałych , które pojawiają się w kontekstach przypisań .
Rozważ następujące przykłady:
char x = 'a' + 'b'; // OK char y = 'a'; char z = y + 'b'; // Compilation error
Co się dzieje? Mają na myśli to samo, prawda? I dlaczego legalne jest przypisanie a
int
dochar
w pierwszym przykładzie ?Gdy stałe wyrażenie pojawia się w kontekście przypisania, kompilator Java oblicza wartość wyrażenia i sprawdza, czy mieści się ona w zakresie typu, do którego przypisujesz. Jeśli tak, jest stosowana niejawna konwersja pierwotna zawężająca .
W pierwszym przykładzie
'a' + 'b'
jest wyrażeniem stałym, a jego wartość zmieści się w achar
, więc kompilator umożliwia niejawne zawężenieint
wyniku wyrażenia do achar
.W drugim przykładzie
y
jest zmienną, więcy + 'b'
NIE jest wyrażeniem stałym. Więc nawet jeśli Blind Freddy widzi, że wartość będzie pasować, kompilator NIE zezwala na żadne niejawne zawężenie, a ty otrzymujesz błąd kompilacji mówiący, żeint
nie można przypisać plikuchar
.Istnieją inne zastrzeżenia co do tego, kiedy w tym kontekście dozwolona jest niejawna, zawężająca konwersja pierwotna ; szczegółowe informacje znajdują się w JLS 5.2 i JLS 15.28 .
Ten ostatni szczegółowo wyjaśnia wymagania dotyczące stałej ekspresji . Może nie być tym, co myślisz. (Na przykład samo zadeklarowanie
y
jakofinal
nie pomaga).źródło