Java >> Tutoriel Java >  >> Java

Types primitifs et variables en Java

Bienvenue dans un autre tutoriel Java ! Si vous suivez, vous venez de finir de jouer avec les nombres dans le volet des interactions de DrJava. Dans ce didacticiel, nous donnerons un contexte à certains des exemples du didacticiel précédent. En particulier, nous couvrirons les types primitifs Java et leur rôle dans la création de variables. Commençons !

Concepts

Avant de vraiment creuser dans le code, nous devons parler des types primitifs et de leurs capacités.

Types de primitives Java

Dans chaque langage de programmation, il existe des types de données qui sont intégrés au langage. Dans des langages comme Java où tous les types de données sont explicites, chacun a un mot-clé unique. Ces mots clés explicites sont utilisés pour dire au langage quel type nous voulons utiliser lorsque nous créons des variables :

variableType variableName; // Declaration
variableName = variableValue; // Definition

La syntaxe ci-dessus est la façon dont nous créons et stockons des données dans une variable. Nous commençons par déclarer le type de données que nous voulons stocker suivi de son nom. Cette partie de la syntaxe est appelée la variable déclaration . Ensuite, nous définissons la variable à l'aide de l'opérateur d'affectation (= ) et une certaine valeur. Bien sûr, il est beaucoup plus simple de créer des variables sur une seule ligne :

variableType variableName = variableValue;

En Java, nous pouvons définir une variable en utilisant l'un des huit types de données intégrés que nous appelons types primitifs :int, double, char, byte, short, long, float et boolean. Par exemple, nous pourrions définir un entier comme suit :

int height = 17;

Dans ce cas, nous avons défini une variable appelée hauteur avec une valeur de 17. Naturellement, nous devrons nous familiariser avec les huit types primitifs, afin de pouvoir les utiliser de manière appropriée.

Opérateurs relationnels Java

Juste au-dessus, nous avons parlé de stocker une valeur numérique dans une variable. Cela dit, Java peut faire bien plus que stocker des numéros. Par exemple, nous pouvons comparer des nombres en utilisant les opérateurs relationnels.

Dans le tutoriel précédent, nous avons été exposés à l'un de ces opérateurs :== . De plus, nous pouvons comparer les valeurs en utilisant != , < , <= , > , et >= . Essayez quelques-uns des exemples suivants :

6 > 7  // 6 is greater than 7 (false)
110 >= 54  // 110 is greater than or equal to 54 (true)
95 < 96  // 95 is less than 96 (true)
63 <= 100  // 63 is less than or equal to 100 (true)

Comme vous l'avez sans doute remarqué, le résultat de chacune de ces opérations est un boolean valeur :true ou false . À l'avenir, nous verrons ces opérateurs être utilisés pour piloter toutes sortes de logiques.

Opérateurs arithmétiques Java

Bien que les opérateurs relationnels soient amusants, nous avons besoin d'opérateurs arithmétiques pour rendre nos expressions plus intéressantes. Jusqu'ici, nous avons introduit des opérateurs arithmétiques au hasard sans vraiment les expliquer. Heureusement, nous allons jeter un œil à tous les opérateurs arithmétiques Java les plus courants :+, -, *, /, %.

Pour commencer, essayez d'exécuter les expressions suivantes et faites attention aux commentaires :

2 + 3  // 2 plus 3 (5)
11 - 5  // 11 minus 5 (6)
13 * 2  // 13 times 2 (26)
6 / 3 // 6 divided by 3 (2)
11 % 2  // remainder of 11 divided by 2 (1)

Dans ce cas, nous avons exécuté les cinq opérateurs sur des entiers. C'est une bonne idée de se familiariser avec ce qui se passerait si vous exécutiez chaque opérateur sur les différents types primitifs. Par exemple, essayez d'utiliser le type double :

2.0 + 3.0  // 2.0 plus 3.0 (5.0)
11.0 - 5.0  // 11.0 minus 5.0 (6.0)
13.0 * 2.0  // 13.0 times 2.0 (26.0)
6.0 / 3.0 // 6.0 divided by 3.0 (2.0)
11.0 % 2.0  // ERROR! Can't compute remainder on doubles

Comme nous le verrons dans la section suivante, les choses deviennent bizarres lorsque nous mélangeons les types dans nos expressions.

Troncation

Bien que l'arithmétique puisse sembler simple, il y a certains pièges dont nous devons être conscients. Après tout, qu'est-ce qu'on s'attend à ce qu'il se passe quand on commence à mélanger des types primitifs ? Par exemple, les expressions suivantes renvoient des résultats différents :

1 + 2  // 3
1 + 2.0  // 3.0

Cela peut sembler idiot, mais cette distinction peut avoir des conséquences. Par exemple, que se passe-t-il si nous échangeons l'addition contre la division ? Il s'avère que quelque chose comme 1 / 2 donnera une valeur de 0. En informatique, nous appelons cela troncature .

La troncature se produit car les entiers 32 bits ne peuvent contenir que des valeurs discrètes. Au lieu d'arrondir la sortie, les entiers suppriment simplement tous les bits qui ne rentrent pas dans la fenêtre 32 bits. Cela est vrai pour tous les types de données, mais il est souvent plus facile de le remarquer avec des nombres entiers.

Bien que la troncature puisse être déroutante et contre-intuitive, elle s'avère utile dans certains cas, comme le mappage. Nous y reviendrons certainement plus tard.

En tout cas, tant que nos types sont cohérents, l'arithmétique est assez simple. Cependant, si nous sommes obligés de mélanger des types compatibles tels que entier et double, Java convertit le résultat entier en type le plus large. En d'autres termes, le type qui a le plus de bits sera le résultat du calcul.

Limites numériques

Un autre problème potentiel avec l'arithmétique est le bouclage . Il s'avère que les nombres dans les systèmes informatiques ont des limites, et les calculs peuvent parfois dépasser ces limites.

Si vous avez eu l'occasion de lire les 8 types primitifs, vous saurez qu'il existe un moyen rapide de vérifier les limites de chaque type primitif. Pour rappel, nous pouvons déterminer la valeur maximale d'un entier à l'aide de l'extrait de code suivant :

Integer.MAX_VALUE

La valeur de retour peut sembler déroutante au premier abord, mais nous réaliserons rapidement que la valeur est la moitié de la plage possible. Cela doit signifier que l'autre moitié de la plage est composée de valeurs négatives. Essayez d'utiliser ce qui suit comme confirmation :

Integer.MIN_VALUE

Pour le plaisir, voyons ce qui se passe lorsque nous dépassons ces limites :

Integer.MAX_VALUE + 1 // Prints -2147483648
Integer.MIN_VALUE - 1 // Prints 2147483647

N'est-ce pas étrange? Nous venons d'observer le bouclage d'entiers pour la première fois. En d'autres termes, une fois que nous avons atteint la limite d'un type primitif, nous passerons de l'autre côté. Gardez cela à l'esprit à mesure que nous avançons.

Au cas où ce ne serait pas déjà clair, un type de données dont la plage est divisée entre des valeurs négatives et positives est appelé un type signé . De même, un type de données qui a une plage entièrement positive est appelé un typé non signé . Dans les deux cas, le langage interprète les bits représentant une valeur.

Type Casting

Le dernier sujet à aborder pour les types primitifs est peut-être cette notion de conversion de type. Nous avons déjà parlé de l'élargissement de type où un calcul est stocké dans le type le plus large. Le casting de type est tout le contraire.

Disons que nous avions un calcul qui donnerait un double, mais nous ne nous soucions pas du résultat décimal. Nous pouvons réduire la précision en utilisant un transtypage en entier. Ceci est utilisé partout dans le code, mais un bon exemple serait une implémentation de l'arrondi. Sans aucune connaissance du flux de contrôle, nous pouvons implémenter l'arrondi :

int round = (int) (7.6 + 0.5);

Dans cet exemple, le nombre que nous essayons d'arrondir au nombre entier le plus proche est 7,6. Si la décimale est inférieure à 0,5, nous voulons que le résultat soit arrondi à l'inférieur. De même, si la décimale est de 0,5 ou plus, nous voulons que le résultat soit arrondi.

En ajoutant .5, on force 7.6 à devenir 8.1. Le transtypage tronque ensuite la virgule décimale, ce qui donne notre entier correctement arrondi. Si le nombre était 7,4, le calcul forcerait 7,4 à 7,9. Ensuite, le transtypage tronquerait la décimale.

Dans cet esprit, nous avons couvert à peu près tout ce que nous pourrions avoir besoin de savoir sur les types primitifs Java.

Pratiquer

À ce stade, nous devrions être assez familiers avec une poignée de concepts, notamment :

  • Déclarations et définitions de variables
  • 8 types primitifs :boolean , int , double , float , byte , short , long , char
  • 5 opérateurs arithmétiques :+ , - , * , / , %
  • 5 opérateurs relationnels :== , >= , > , < , <=
  • Troncation
  • Type de coulée
  • Limites numériques

À ce stade, nous allons tout rassembler avec quelques exemples. Dans le volet des interactions, essayez ce qui suit :

char letter = 'b';

Plus tôt, nous avons écrit une ligne similaire où nous avons attribué à une variable une valeur de 7. Dans ce cas, nous travaillions avec des nombres entiers. Dans ce cas, nous travaillons avec le char type primitif qui peut stocker des valeurs de caractères. Avec cette ligne, nous avons maintenant stocké notre propre valeur dans une variable appelée lettre. Allez-y et expérimentez avec les différents types de données. Par exemple, nous pourrions essayer l'une des actions suivantes :

boolean hasMoney = true; 
int hour = 7; 
double height = 13.7; 
float gravity = 9.81f; 
long sixBillion = 6000000000L;

Maintenant que nous avons déclaré certaines variables, essayez d'ajouter certaines de ces valeurs et notez les résultats. Par exemple :

hour + height;

Les noms de variables n'ont pas beaucoup de sens, mais cela est parfaitement légal et se traduira par 20,7. Cependant, si nous essayons quelque chose comme :

hasMoney + hour;

Nous finirons par une erreur. C'est parce que nous essayons d'ajouter un booléen à un entier. En attendant, ce qui suit est tout à fait légal en Java :

char gravity = 'g'; 
char speedOfLight = 'c'; 
gravity + speedOfLight;

On peut en effet additionner ces caractères ensemble ce qui donne 202 ou ‘Ê’. Parce que le type char est en fait une valeur numérique, nous pouvons les additionner comme des entiers.

L'ajout de caractères est particulièrement pratique si nous voulons comparer des caractères pour la commande. Par exemple, deux lettres peuvent être comparées par ordre alphabétique en comparant leurs valeurs numériques. Une liste complète de tous les caractères ASCII disponibles et de leurs valeurs peut être trouvée ici.

De plus, les caractères Java sont 16 bits, ce qui leur donne une plus grande variété que les 256 caractères ASCII. De plus, le type primitif char est le seul type primitif Java non signé.

Mais qu'en est-il des chaînes ?

Puisque nous sommes sur le sujet des caractères, parlons des chaînes. Java prend en charge nativement les chaînes qui sont des séquences de caractères. Cependant, les chaînes ne sont pas un type primitif Java. Ils sont plutôt un type de référence .

Un type référence est un peu différent d'un type primitif. Avec les types primitifs, nous sommes libres de copier et de comparer les données selon les besoins. Cela rend le développement extrêmement intuitif grâce à ce concept appelé sémantique des valeurs . La sémantique des valeurs implique que les variables sont immuables, nous n'avons donc pas à nous soucier d'une copie corrompant la valeur d'origine.

Pour tester ce concept, essayez ce qui suit dans le volet des interactions de DrJava :

int x = 5; 
int y = 5; 
y == x;

Notez que cette comparaison renvoie true comme prévu. Intuitivement, 5 est égal à 5. Essayez maintenant ce qui suit :

String firstName = "Leroy"; 
String lastName = "Leroy"; 
firstName == lastName;

Dans cet exemple, nous définissons deux composants du nom de quelqu'un :Leroy Leroy. Intuitivement, nous penserions que la comparaison des deux noms renverrait true. Après tout, les deux noms ont les mêmes lettres et les deux noms sont sensibles à la casse. Cependant, nous obtenons un résultat choquant de false .

Il s'avère que le == L'opérateur ne compare pas les chaînes comme prévu. La raison de la mauvaise comparaison sera expliquée plus en détail dans le didacticiel suivant, alors pour l'instant, essayez de comparer plus de chaînes. Par exemple, nous pourrions essayer de créer deux chaînes et de les affecter l'une à l'autre :

String firstName = "Leroy"; 
String lastName = "Jenkins"; 
firstName = lastName; 
firstName == lastName;

Dans ce cas, la comparaison utilisant == résultats en true . Bien sûr, la comparaison de valeurs est la même, alors pourquoi renverrait-elle true cette fois? Dans le prochain didacticiel, nous examinerons plus en détail les chaînes et ce qui se passe réellement lorsque nous effectuons une comparaison à l'aide de == .

Soyez prudent ! Si vous utilisez presque n'importe quel outil autre que le volet d'interactions de DrJava, vous pouvez constater que des expressions telles que "Leroy" == "Leroy" retourner vrai. Cela est dû à une fonctionnalité spéciale de Java appelée string interning (merci, Iven) qui garantit que les constantes de chaîne en double ont la même référence. En d'autres termes, nous ne comparons toujours pas le contenu de la chaîne. Plus d'informations à ce sujet plus tard !


Balise Java