web-dev-qa-db-fra.com

En Java, le résultat de l'ajout de deux caractères est-il un entier ou un caractère?

Lors de l'ajout de 'a' + 'b' il produit 195. Le type de données de sortie est-il char ou int?

71
orange

Le résultat de l'ajout de Java caractères, courts métrages ou octets est un int :

Spécification du langage Java sur la promotion numérique binaire :

  • Si l'un des opérandes est de type référence, une conversion de déballage (§5.1.8) est effectuée. Ensuite:
  • Si l'un des opérandes est de type double, l'autre est converti en double.
  • Sinon, si l'un des opérandes est de type float, l'autre est converti en float.
  • Sinon, si l'un des opérandes est de type long, l'autre est converti en long.
  • Sinon, les deux opérandes sont convertis en type int.

Mais notez ce qu'il dit sur les opérateurs d'affectation composés (comme + =) :

Le résultat de l'opération binaire est converti dans le type de la variable de gauche ... et le résultat de la conversion est stocké dans la variable.

Par exemple:

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

Une façon de découvrir le type du résultat, en général, est de le convertir en objet et de lui demander de quelle classe il s'agit:

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

Si vous êtes intéressé par les performances, notez que Java bytecode n'a même pas d'instructions dédiées pour l'arithmétique avec les types de données plus petits. Par exemple, pour l'ajout, il existe des instructions iadd (pour les entiers), ladd (pour les longs), fadd (pour les flottants), dadd (pour doubles), et c'est tout. Pour simuler x += y Avec les types plus petits, le compilateur utilisera iadd puis mettra à zéro les octets supérieurs de l'int en utilisant une instruction comme i2c ("Int to char"). Si le CPU natif a des instructions dédiées pour les données à 1 ou 2 octets, c'est à la machine virtuelle Java à optimiser pour cela au moment de l'exécution).

Si vous souhaitez concaténer des caractères sous forme de chaîne plutôt que de les interpréter comme un type numérique, il existe de nombreuses façons de procéder. Le plus simple est d'ajouter une chaîne vide à l'expression, car l'ajout d'un caractère et d'une chaîne entraîne une chaîne. Toutes ces expressions donnent la chaîne "ab":

  • 'a' + "" + 'b'
  • "" + 'a' + 'b' (Cela fonctionne parce que "" + 'a' Est évalué en premier; si le "" Était à la fin, vous obtiendriez "195")
  • new String(new char[] { 'a', 'b' })
  • new StringBuilder().append('a').append('b').toString()
  • String.format("%c%c", 'a', 'b')
122
Boann

Les opérations arithmétiques binaires sur char et byte (et short) sont converties en int - JLS 5.6.2.

20
Hot Licks

Vous souhaiterez peut-être apprendre les expressions suivantes à propos de char.

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

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

Ceci est parfaitement valide dans Java et renvoie 66, la valeur correspondante du caractère (Unicode) de c+1.


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

Ceci est trop valide dans Java et la variable de type String temp accepte automatiquement c de type char et produit temp=A sur la console.


Toutes les déclarations suivantes sont également valables en 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);

Bien que c soit un type de char, il peut être fourni sans erreur dans les constructeurs respectifs et toutes les instructions ci-dessus sont traitées comme des instructions valides. Ils produisent respectivement les sorties suivantes.

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

char est un type intégral numérique primitif et en tant que tel est soumis à toutes les règles de ces bêtes, y compris les conversions et les promotions. Vous aurez envie de lire à ce sujet, et le JLS est l'une des meilleures sources pour cela: Conversions et promotions . En particulier, lisez le petit morceau sur "5.1.2 Elargissement de la conversion primitive".

7
Lion

Le compilateur Java peut l'interpréter comme l'un ou l'autre.

Vérifiez-le en écrivant un programme et en recherchant les erreurs du compilateur:

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

Si c'est un caractère, la première ligne me donnera une erreur et la seconde non. Si c'est un int, alors l'inverse se produira.

Je l'ai compilé et j'ai obtenu ..... AUCUNE ERREUR. Donc Java accepte les deux.

Cependant, quand je les ai imprimés, j'ai eu:

int: 195

char: Ã

Ce qui se passe, c'est que lorsque vous faites:

char result2 = 'a' + 'b'

une conversion implicite est effectuée (une "conversion de rétrécissement primitive" de int en char ).

3
eboix

Selon les règles de promotion binaires , si aucun des opérandes n'est double, flottant ou long, les deux sont promus en int. Cependant, je déconseille fortement de traiter le type de char comme numérique, ce qui va à l'encontre de son objectif.

2
Sergei Tachenov

char est représenté par des valeurs Unicode et où les valeurs Unicode sont représentées par \u suivi de Hexadecimal valeurs.

Comme toute opération arithmétique sur char valeurs promues en int, le résultat de 'a' + 'b' est calculé comme

1.) Appliquez les valeurs Unicode aux char correspondants en utilisant Unicode Table

2.) Appliquez la conversion Hexadécimal à Décimal puis effectuez l'opération sur les valeurs Decimal.

    char        Unicode      Decimal
     a           0061          97
     b           0062          98  +
                              195

Unicode To Decimal Converter

Exemple

0061

(0 * 163) + (0 * 162) + (6 * 161) + (1 * 16)

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

0 + 0 + 96 + 1 = 97

0062

(0 * 163) + (0 * 162) + (6 * 161) + (2 * 16)

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

0 + 0 + 96 + 2 = 98

Par conséquent 97 + 98 = 195


Exemple 2

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

Bien que vous ayez déjà la bonne réponse (référencée dans le JLS), voici un peu de code pour vérifier que vous obtenez un int lorsque vous ajoutez deux chars.

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

La sortie est

Java.lang.Integer

1
Paul

Voici quelque chose d'étrange, cependant. Les compilations suivantes:

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

Mais cela ne signifie pas:

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

Il semblerait que les deux expressions ('a' + 'b' et x + 'b') donnent des entiers, par le test suivant:

Object obj = 'a'+'b';
System.out.println(obj.getClass().getName());

char x = 'a';
Object obj2 = x+'b';
System.out.println(obj2.getClass().getName());

Alors pourquoi le deuxième cas ne se compilerait-il pas? Soit dit en passant, vous pouvez le corriger en convertissant l'expression entière en caractère:

x = (char)(x+'b');

Cela semble être une incohérence dans la sémantique de Java - toute expression char doit être interchangeable avec une autre dans n'importe quel contexte. Quelqu'un connaît-il un moyen de donner un sens à cela?

0
Sam Scott