Hej! Efterhånden som du er kommet videre gennem CodeGym, har du stødt på primitive typer mange gange. Her er en kort liste over, hvad vi ved om dem:
- De er ikke objekter og repræsenterer en værdi, der er gemt i hukommelsen
- Der er flere slags
- Hele tal: byte , kort , int , lang
- Flydende tal (brøktal): flydende og dobbelt
- Logiske værdier: boolesk
- Symbolske værdier (til at repræsentere bogstaver og tal): char
-
Hver type har sit eget værdiområde:
Primitiv type |
Størrelse i hukommelsen |
Værdiinterval |
byte |
8 bits |
-128 til 127 |
kort |
16 bits |
-32768 til 32767 |
char |
16 bits |
0 til 65536 |
int |
32 bit |
-2147483648 til 2147483647 |
lang |
64 bit |
-9223372036854775808 til 9223372036854775807 |
flyde |
32 bit |
(2 i potens af -149) til ((2 - (2 i potens af -23)) * 2 i potens af 127) |
dobbelt |
64 bit |
(-2 i potens af 63) til ((2 i potens af 63) - 1) |
boolesk |
8 (når brugt i arrays), 32 (hvis ikke brugt i arrays) |
sandt eller falsk |
Men udover at have forskellige værdier, er de også forskellige i, hvor meget plads de optager i hukommelsen. En
int tager mere end en byte. Og en
lang er større end en kort. Mængden af hukommelse optaget af primitiver kan sammenlignes med russiske rededukker:
Hver rededukke har ledig plads indeni. Jo større rededukken er, jo mere plads er der. En stor rededukke (
lang ) vil nemt kunne rumme en mindre
int . Det passer nemt, og du behøver ikke at gøre andet. I Java, når man arbejder med primitiver, kaldes dette implicit konvertering. Eller sagt anderledes, det kaldes udvidelse.
Udvidelse i Java
Her er et simpelt eksempel på en udvidende konvertering:
public class Main {
public static void main(String[] args) {
int bigNumber = 10000000;
byte littleNumber = 16;
bigNumber = littleNumber;
System.out.println(bigNumber);
}
}
Her tildeler vi en byteværdi til en
int- variabel. Tildelingen lykkes uden problemer: værdien gemt i en byte fylder mindre hukommelse end hvad en
int kan rumme. Den lille rededukke (byteværdi) passer nemt ind i den store rededukke (
int variabel). Det er en anden sag, hvis man forsøger at gøre det modsatte, altså at lægge en stor værdi ind i en variabel, hvis rækkevidde ikke kan rumme så stor en datatype. Med rigtige rededukker ville nummeret simpelthen ikke passe. Med Java kan det, men med nuancer. Lad os prøve at sætte en
int i en
kort variabel:
public static void main(String[] args) {
int bigNumber = 10000000;
short littleNumber = 1000;
littleNumber = bigNumber;
System.out.println(bigNumber);
}
Fejl! Compileren forstår, at du forsøger at gøre noget unormalt ved at skubbe en stor rededukke (
int ) ind i en lille (
kort ). I dette tilfælde er kompileringsfejlen en advarsel fra compileren: "Hej, er du
helt sikker på , at du vil gøre dette?" Hvis du er sikker, så siger du til compileren:
"Alt er okay. Jeg ved, hvad jeg laver!" Denne proces kaldes eksplicit typekonvertering eller indsnævring.
Indsnævring i Java
For at udføre en indsnævre konvertering skal du udtrykkeligt angive den type, du vil konvertere din værdi til. Du skal med andre ord svare på kompilatorens spørgsmål:
"Nå, hvilken af disse små rededukker vil du putte denne store rededukke i?" I vores tilfælde ser det sådan ud:
public static void main(String[] args) {
int bigNumber = 10000000;
short littleNumber = 1000;
littleNumber = (short) bigNumber;
System.out.println(littleNumber);
}
Vi angiver udtrykkeligt, at vi ønsker at sætte en
int i en
kort variabel, og at vi tager ansvaret. Når du ser, at en smallere type er blevet eksplicit angivet, udfører compileren konverteringen. Hvad er resultatet? Konsol output:
-27008 Det var lidt uventet. Hvorfor fik vi det præcist? Faktisk er det hele meget enkelt. Oprindeligt var værdien 10000000. Den blev gemt i en
int- variabel, som optager 32 bit. Dette er dens binære repræsentation:
Vi skriver denne værdi ind i en
kort variabel, som kun kan lagre 16 bit! Derfor vil kun de første 16 bits af vores nummer blive flyttet dertil. Resten vil blive kasseret. Som et resultat modtager den korte variabel følgende værdi
som i decimalform er lig med -27008 Det er derfor, compileren beder dig om at "bekræfte" ved at angive en eksplicit indsnævringskonvertering til en bestemt type. For det første viser dette, at du tager ansvar for resultatet. Og for det andet fortæller den compileren, hvor meget plads der skal tildeles, når konverteringen sker. Når alt kommer til alt, i det sidste eksempel, hvis vi tildelte en int-værdi til en byte-variabel i stedet for en
short , ville vi kun have 8 bits til vores rådighed, ikke 16, og resultatet ville være anderledes. Fraktionelle typer (
float og
double ) har deres egen proces til at indsnævre konverteringer. Hvis du prøver at caste et fraktionstal til en heltalstype, vil brøkdelen blive kasseret.
public static void main(String[] args) {
double d = 2.7;
long x = (int) d;
System.out.println(x);
}
Konsoludgang:
2
char
Du ved allerede, at
tegn bruges til at vise individuelle tegn.
public static void main(String[] args) {
char c = '!';
char z = 'z';
char i = '8';
}
Men denne datatype har flere funktioner, som er vigtige at forstå. Lad os se igen på tabellen over værdiintervaller:
Primitiv type |
Størrelse i hukommelsen |
Værdiinterval |
byte |
8 bits |
-128 til 127 |
kort |
16 bits |
-32768 til 32767 |
char |
16 bits |
0 til 65536 |
int |
32 bit |
-2147483648 til 2147483647 |
lang |
64 bit |
-9223372036854775808 til 9223372036854775807 |
flyde |
32 bit |
(2 i potens af -149) til ((2 - (2 i potens af -23)) * 2 i potens af 127) |
dobbelt |
64 bit |
(-2 i potens af 63) til ((2 i potens af 63) - 1) |
boolesk |
8 (når brugt i arrays), 32 (hvis ikke brugt i arrays) |
sandt eller falsk |
Området 0 til 65536 er angivet for
char- typen. Men hvad betyder det? Når alt kommer til alt, repræsenterer et
tegn ikke kun tal, men også bogstaver, tegnsætningstegn... Sagen er, at i Java er
tegnværdier gemt i Unicode-format. Vi stødte allerede på Unicode i en af de tidligere lektioner. Du husker sikkert, at Unicode er en tegnkodningsstandard, der indeholder symbolerne på næsten alle verdens skriftsprog. Med andre ord er det en liste over specielle koder, der repræsenterer næsten alle tegn på ethvert sprog. Hele Unicode-bordet er meget stort, og det er selvfølgelig ikke nødvendigt at lære det udenad. Her er en lille del af det:
Det vigtigste er at forstå, hvordan tegn gemmes, og at huske, at hvis du kender koden for et bestemt tegn, kan du altid producere det tegn i dit program. Lad os prøve med et tilfældigt tal:
public static void main(String[] args) {
int x = 32816;
char c = (char) x ;
System.out.println(c);
}
Konsoloutput: 耰 Dette er formatet, der bruges til at gemme
tegn i Java. Hvert symbol svarer til et tal: en 16-bit (to-byte) numerisk kode. I Unicode svarer 32816 til det kinesiske tegn 耰. Bemærk følgende punkt. I dette eksempel brugte vi en
int -variabel. Den optager 32 bits i hukommelsen, mens en
char optager 16. Her valgte vi en
int , fordi vores nummer (32816) ikke passer i en
kort . Selvom størrelsen af en
char (ligesom en
short ) er 16 bit, er der ingen negative tal i
char- området, så den "positive" del af
charrækkevidden er dobbelt så stor (65536 i stedet for 32767 for den
korte type). Vi kan bruge en
int , så længe vores kode forbliver under 65536. Men hvis du opretter en
int- værdi større end 65536, så vil den optage mere end 16 bit. Og dette vil resultere i en indsnævrende konvertering
char c = (char) x;
de ekstra bits vil blive kasseret (som diskuteret ovenfor), og resultatet vil være ret uventet.
Særlige funktioner ved tilføjelse af tegn og heltal
Lad os se på et usædvanligt eksempel:
public class Main {
public static void main(String[] args) {
char c = '1';
int i = 1;
System.out.println(i + c);
}
}
Konsoludgang:
50 O_О Hvordan giver det mening? 1+1. Hvor kom de 50 fra?! Du ved allerede, at
char
værdier er gemt i hukommelsen som tal i området fra 0 til 65536, og at disse tal er en Unicode-repræsentation af et tegn.
Når vi tilføjer et
tegn og en eller anden heltalstype, konverteres
tegnet til det tilsvarende Unicode-nummer. I vores kode, da vi tilføjede 1 og '1', blev symbolet '1' konverteret til sin egen kode, som er 49 (du kan bekræfte dette i tabellen ovenfor). Derfor er resultatet 50. Lad os endnu en gang tage vores gamle ven 耰 som eksempel, og prøve at tilføje det til et eller andet tal.
public static void main(String[] args) {
char c = '耰';
int x = 200;
System.out.println(c + x);
}
Konsol output:
33016 Vi har allerede opdaget, at 耰 svarer til 32816. Og når vi tilføjer dette tal og 200, får vi vores resultat: 33016. :) Som du kan se, er algoritmen her ret simpel, men du skal ikke glemme den .