Lors de l'ajout de 'a' + 'b'
il produit 195. Le type de données de sortie est-il char
ou int
?
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')
Les opérations arithmétiques binaires sur char
et byte
(et short
) sont converties en int
- JLS 5.6.2.
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".
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 ).
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.
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
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 %
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 char
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());
}
}
La sortie est
Java.lang.Integer
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?