Ist das Ergebnis der Addition von zwei Zeichen in Java ein int oder ein char?


80

Beim Hinzufügen 'a' + 'b'werden 195 ausgegeben. Ist der Ausgabedatentyp charoder int?


2
Wenn der Typ wäre, wäre charder Wert von 'a' + 'b'nicht 195aber'Ã'
Joren

1
Es ist 195 hier - ideone.com, aber nicht in Eclipse.
Orange

2
Sie lesen das aus dem Algorithmus-Buch lol! Ich kam wegen dieser Übung genau hierher;)
Jack Twain

Antworten:


132

Das Ergebnis des Hinzufügens von Java-Zeichen, Kurzschlüssen oder Bytes ist ein int :

Java-Sprachspezifikation zur binären numerischen Förderung :

  • Wenn einer der Operanden vom Referenztyp ist, wird die Unboxing-Konvertierung (§5.1.8) durchgeführt. Dann:
  • Wenn einer der Operanden vom Typ double ist, wird der andere in double konvertiert.
  • Wenn einer der Operanden vom Typ float ist, wird der andere in float konvertiert.
  • Wenn einer der Operanden vom Typ long ist, wird der andere in long konvertiert.
  • Andernfalls werden beide Operanden in den Typ int konvertiert.

Beachten Sie jedoch, was es über zusammengesetzte Zuweisungsoperatoren sagt (wie + =) :

Das Ergebnis der Binäroperation wird in den Typ der linken Variablen konvertiert ... und das Ergebnis der Konvertierung wird in der Variablen gespeichert.

Zum Beispiel:

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

Eine Möglichkeit, den Typ des Ergebnisses im Allgemeinen herauszufinden, besteht darin, es in ein Objekt umzuwandeln und zu fragen, um welche Klasse es sich handelt:

System.out.println(((Object)('a' + 'b')).getClass());
// outputs: class java.lang.Integer

Wenn Sie an Leistung interessiert sind, beachten Sie, dass der Java-Bytecode nicht einmal spezielle Anweisungen für die Arithmetik mit den kleineren Datentypen enthält. Zum Hinzufügen gibt es zum Beispiel Anweisungen iadd(für Ints), ladd(für Longs), fadd(für Floats), dadd(für Doubles), und das war's. Um x += ymit den kleineren Typen zu simulieren , verwendet der Compiler iadddie oberen Bytes des int und setzt sie dann mit einer Anweisung wie i2c("int to char") auf Null . Wenn die native CPU über dedizierte Anweisungen für 1-Byte- oder 2-Byte-Daten verfügt, muss die virtuelle Java-Maschine dies zur Laufzeit optimieren.

Wenn Sie Zeichen als Zeichenfolge verketten möchten, anstatt sie als numerischen Typ zu interpretieren, gibt es viele Möglichkeiten, dies zu tun. Am einfachsten ist es, dem Ausdruck einen leeren String hinzuzufügen, da das Hinzufügen eines Zeichens und eines Strings zu einem String führt. Alle diese Ausdrücke führen zum String "ab":

  • 'a' + "" + 'b'
  • "" + 'a' + 'b'(Dies funktioniert, weil "" + 'a'zuerst ausgewertet wird; wenn die ""am Ende stattdessen wären, würden Sie bekommen "195")
  • new String(new char[] { 'a', 'b' })
  • new StringBuilder().append('a').append('b').toString()
  • String.format("%c%c", 'a', 'b')


7

Möglicherweise möchten Sie die folgenden Ausdrücke über lernen char.

char c='A';
int i=c+1;

System.out.println("i = "+i);

Dies ist in Java vollkommen gültig und gibt 66den entsprechenden Wert des Zeichens (Unicode) von zurück c+1.


String temp="";
temp+=c;
System.out.println("temp = "+temp);

Dies ist in Java zu gültig und die Variable vom Typ String tempakzeptiert automatisch den cTyp char und erzeugt temp=Aauf der Konsole.


Alle folgenden Aussagen gelten auch in Java!

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

Obwohl ces sich um eine Art von handelt char, kann es in den jeweiligen Konstruktoren fehlerfrei angegeben werden, und alle obigen Anweisungen werden als gültige Anweisungen behandelt. Sie erzeugen jeweils die folgenden Ausgaben.

intType = 65
doubleType = 65.0
floatType = 65.0
decimalType = 65
longType =65

charist ein primitiver numerischer Integraltyp und unterliegt als solcher allen Regeln dieser Bestien, einschließlich Umbauten und Beförderungen. Sie sollten sich darüber informieren, und das JLS ist eine der besten Quellen dafür: Conversions und Promotions . Lesen Sie insbesondere das kurze Bit zu "5.1.2 Erweitern der primitiven Konvertierung".


3

Der Java-Compiler kann es als eines von beiden interpretieren.

Überprüfen Sie dies, indem Sie ein Programm schreiben und nach Compilerfehlern suchen:

public static void main(String[] args) {
    int result1 = 'a' + 'b';
    char result2 = 'a' + 'b';
}

Wenn es ein Zeichen ist, gibt mir die erste Zeile einen Fehler und die zweite nicht. Wenn es ein int ist, wird das Gegenteil passieren.

Ich habe es zusammengestellt und ich habe ... KEINE FEHLER. Java akzeptiert also beides.

Als ich sie jedoch druckte, bekam ich:

int: 195

char: Ã

Was passiert ist, wenn Sie Folgendes tun:

char result2 = 'a' + 'b'

Es wird eine implizite Konvertierung durchgeführt (eine "primitive Verengungskonvertierung" von int nach char ).


Ich bin überrascht, dass Sie im zweiten Fall keine Compiler-Warnung über einen möglichen Genauigkeitsverlust aufgrund einer Verengung erhalten haben.
Hot Licks

@eboix: Sie haben geschrieben "Der Compiler wandelt automatisch entweder in char oder int um" [sic] ... Was nicht korrekt ist, weil ein int nicht in ein int "umgewandelt" wird und der Übergang von einem int zu einem char nicht aufgerufen wird eine "Besetzung", aber eine "sich verengende primitive Bekehrung"; )
TacticalCoder

Ja. Das habe ich auch erwartet. Ich hatte tatsächlich einen Teil meiner Antwort darüber geschrieben, bevor ich mein Programm erstellt habe, aber dann habe ich es gelöscht, als ich sah, dass ich keine Warnungen oder Fehler bekam.
Eboix

@eboix: eh eh :) Ich hätte es bearbeitet, aber ich habe noch keine 2 000 Reputationspunkte, daher mein Kommentar anstelle einer Bearbeitung; )
TacticalCoder

Wenn Sie möchten, @ user988052, kann ich es wieder in das ändern, was es war, und Sie können es bearbeiten, um Punkte zu erhalten. Sie können es weiterhin bearbeiten, wenn Sie weniger als 2000 Reputationspunkte haben. Das einzige ist, dass die Person, die den Beitrag verfasst hat, die Bearbeitung akzeptieren muss. Ich werde es jetzt wieder ändern, damit Sie die zwei Punkte erhalten, die Ihnen zu Recht gehören.
eboix

1

Gemäß den binären Heraufstufungsregeln werden beide zu int heraufgestuft, wenn keiner der Operanden double, float oder long ist. Ich rate jedoch dringend davon ab, den Zeichentyp als numerisch zu behandeln, da dies seinen Zweck zunichte macht.


1
Die Verwendung charals numerischer Wert liegt vollständig in seinem Zweck, weshalb das JLS einer solchen Verwendung so viel Wortschatz widmet.
Lew Bloch

1

Während Sie bereits die richtige Antwort haben (auf die im JLS verwiesen wird), finden Sie hier einen Code, mit dem Sie überprüfen können, ob Sie intbeim Hinzufügen von zwei chars eine erhalten.

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

Die Ausgabe ist

java.lang.Integer


Dies ist keine überzeugende Bestätigung, da Sie eine Box-Konvertierung in die Mischung geworfen haben. Die Typen intund Integersind nicht dasselbe. Eine überzeugendere Überprüfung besteht darin, zu versuchen, a + beiner intVariablen oder einer charVariablen zuzuweisen . Letzteres gibt einen Übersetzungsfehler , die in der Tat sagt : „Sie können nicht zuordnen intzu einem char“.
Stephen C

0

charwird als UnicodeWerte dargestellt und wobei Unicode-Werte \ugefolgt von HexadecimalWerten dargestellt werden.

Wie jede arithmetische Operation für charWerte, auf die heraufgestuft wird, intwird das Ergebnis von 'a' + 'b'als berechnet

1.) Wenden Sie die UnicodeWerte auf die entsprechende charVerwendung anUnicode Table

2.) Wenden Sie die Hexadezimal-Dezimal- Konvertierung an und führen Sie dann die Operation für DecimalWerte aus.

    char        Unicode      Decimal
     a           0061          97
     b           0062          98  +
                              195

Unicode To Decimal Converter

Beispiel

0061

(0 * 16 3 ) + (0 * 16 2 ) + (6 * 16 1 ) + (1 * 16 0 )

(0 * 4096) + (0 * 256) + (6 * 16) + (1 * 1)

0 + 0 + 96 + 1 = 97

0062

(0 * 16 3 ) + (0 * 16 2 ) + (6 * 16 1 ) + (2 * 16 0 )

(0 * 4096) + (0 * 256) + (6 * 16) + (2 * 1)

0 + 0 + 96 + 2 = 98

Daher 97 + 98 = 195


Beispiel 2

char        Unicode      Decimal
 Ջ           054b         1355
 À           00c0          192 
                      --------
                          1547    +
                          1163    -
                             7    /
                        260160    *
                            11    %

Darum geht es in der Frage nicht.
Stephen C

Zu Ihrer Information, meine detaillierte Antwort auf den obigen Kommentar wurde von Mods entfernt, die den Grund für die Migration meiner Antwort von einem gelöschten Beitrag erklärten. Wenn meine Antwort gelöscht wurde, um die Fehler der SO-Moderation zu vertuschen, können Sie dann zumindest den obigen Kommentar entfernen oder das Publikum irgendwie angeben, damit ich keinen weiteren Kommentar schreiben muss? Fragen an SO Mods
Pavneet_Singh

Ich stehe zu meinem Kommentar. Wie ich Ihnen geantwortet habe ... aber dann gelöscht habe ... ändert der Grund, warum Sie diese Frage hier gepostet haben, nichts an der Tatsache, dass sie zu 95% vom Thema abweicht und 5% frühere Antworten wiederholt. Wenn Sie die Ergebnisse Ihrer verschwendeten Arbeit speichern möchten, ist es besser, sie auf Ihrer Festplatte zu speichern. Oder finden Sie eine andere Frage, für die es relevant ist.
Stephen C

Wenn Sie Probleme mit den Moderatoren haben, nehmen Sie diese in meta.stackoverflow.com auf. Und Beweise vorlegen. Alles, was ich hier versuche, ist >> diese << Fragen und Antworten aufzuräumen.
Stephen C

Ich verstehe Ihre Ansicht, kann aber nicht verstehen, dass die Details der Unicode-Konvertierung anhand von Beispielen ignoriert werden. Dies ist ein zusätzlicher Wert, der einigen Lesern helfen könnte. Daher möchte ich diese Antwort behalten (ich verstehe, dass sie für Sie nicht nützlich ist und falsch erscheint). Thema). Ich vermeide Meta und ähnliche Orte, da es nicht einfach ist, solche Dinge ohne Kraft oder Unterstützung zu tun, was viel Zeit und Mühe kostet. Ich ziehe es vor, meinen inneren Frieden zu bewahren.
Pavneet_Singh

0

Während Boanns Antwort richtig ist, gibt es eine Komplikation, die für den Fall konstanter Ausdrücke gilt, wenn sie in Zuweisungskontexten erscheinen .

Betrachten Sie die folgenden Beispiele:

  char x = 'a' + 'b';   // OK

  char y = 'a';
  char z = y + 'b';     // Compilation error

Was ist los? Sie bedeuten dasselbe, nicht wahr? Und warum ist es legal, im ersten Beispiel ein inta zuzuweisen char?

Wenn ein konstanter Ausdruck in einem Zuweisungskontext angezeigt wird, berechnet der Java-Compiler den Wert des Ausdrucks und prüft, ob er im Bereich des Typs liegt, dem Sie zuweisen. Wenn dies der Fall ist, wird eine implizite Verengung der primitiven Konvertierung angewendet.

  • Im ersten Beispiel 'a' + 'b'handelt es sich um einen konstanten Ausdruck, dessen Wert in a passt char, sodass der Compiler die implizite Eingrenzung des intAusdrucksergebnisses auf a zulässt char.

  • Im zweiten Beispiel yhandelt es sich um eine Variable, also y + 'b'NICHT um einen konstanten Ausdruck. Obwohl Blind Freddy sehen kann, dass der Wert passt, lässt der Compiler KEINE implizite Verengung zu, und Sie erhalten einen Kompilierungsfehler, der besagt, dass a intnicht zugewiesen werden kann char.

Es gibt einige andere Vorbehalte, wenn in diesem Zusammenhang eine implizite Verengung der primitiven Konvertierung zulässig ist. Ausführliche Informationen finden Sie in JLS 5.2 und JLS 15.28 .

Letzteres erklärt ausführlich die Anforderungen an einen konstanten Ausdruck . Es kann nicht sein, was Sie vielleicht denken. (Zum Beispiel hilft es nicht , nur yals zu deklarieren final.)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.