1. Nyckelord
Det finns 8 nyckelord som har att göra med typer. I Java finns det 8 primitiva typer, som alltså inte är klasser utan faktiskt minnesallokeringar. I tabellen nedan använder jag komma (,) mitt i stora tal för att man lättare ska kunna se hur stora de är (på amerikanskt vis):
Datatyp | | Bitar | | Default | | Beskrivning |
boolean | | - | | false | | true,false |
byte | | 8 | | 0 (noll) | | -2^7 till 2^7-1 (-128 till 127) |
short | | 16 | | 0 (noll) | | -2^15 till 2^15-1 (-32,768 till 32,767) |
char | | 16 | | 0 (noll) | | 0 till 2^16 (0 till 65,536) |
int | | 32 | | 0 (noll) | | -2^31 till 2^31-1 (-2,147,483,648 till 2,147,483,647) |
long | | 64 | | 0 (noll) | | -2^63 till 2^63-1 (-9,223,372,036,854,775,808 till 9,223,372,036,854,775,807) |
float | | 32 | | 0.0 (noll) | | 10^-45 till 10^38 |
double | | 64 | | 0.0 (noll) | | 10^-324 till 10^308 |
Typen boolean kan anta true och false, som är reserverade ord.
2. Litterärer
En litterär är data som skrivs ut i klartext i programmet, t.ex. 17. Nedan ges exempel på olika litterärer och hur Java tolkar dessa literärer. Vi listar några olika litterärer och deras respektive typ:
Litterär | | Datatyp | | Beskrivning |
17 | | int | | Ett heltal blir automaitskt int. |
017 | | int | | Ett heltal som börjar på 0 tolkas med basen 8 (=15). |
0x17 | | int | | Ett heltal som börjar på 0x tolkas med basen 16 (=23). |
17L | | long | | Vill man ha en long måste talet sluta på L/l. |
0x17L | | long | | Ett heltal som börjar på 0x tolkas med basen 16 (=23). L/l förvandlar litterären till long. |
17.0 | | double | | Ett decimaltal blir automatiskt en double. |
17.0F | | float | | Vill man ha en float måste talet sluta på F/f. |
17F | | float | | Även heltal omvandlas med F/f. |
0x17F | | int | | För heltal med basen 16 förvandlar F/f ej litterären till float (=383). |
true | | boolean | | Detta nyckelord är en boolean. |
false | | boolean | | Detta nyckelord är en boolean. |
'a' | | char | | Tecken inom enkelfnuttar är char. |
'\u00A0' | | char | | Detta representerar ett Unicodetecken. |
Några regler som kan läggas på minnet är:
- Heltal som slutar på L eller l omvandlas till typen long.
- Tal (ej basen 16) som slutar på F eller f omvandlas till typen float.
3. Initiering
De primitiva typerna kan initieras på följande vis:
- 1. Med en variabel eller ett uttryck.
- 2. Med en litterär.
Följande exempel visar hur initiering med litterär kan gå till.
class TestLiteralInit{
public static void main(String[] args){
int i=4;
long l=4L, k=0xF2L;
float f=4F;
double d=4.1;
char c='a';
System.out.println("i="+i+" l="+l+" k="+k+" f="+f+" d="+d+" c="+c);
}
}
|
Vi får utskriften:
[olle@dev1]$ java TestLiteralInit
i=4 l=4 k=242 f=4.0 d=4.1 c=a
|
4. Explicit typkonvertering
Om en typ ska konverteras till någon annan kan man göra det explicit, dvs. att man skiver ut den nya typen inom parantes precis efter likamedtecknet. Typer kan konverteras hur som helst sinsemellan, utom i fallet boolean. boolean kan inte konverteras till eller från någon annan typ. Här kommer ett exempel på en explicit konvertering:
class TestTypeConvert{
public static void main(String[] args){
int i=(int) 4.3;
System.out.println("i="+i);
}
}
|
Vi kör programmet och får följande:
[olle@dev1]$ javac TestTypeConvert
i=4
|
Här konverterades 4.3 till 4 och vi förlorade den data som kom efter decimaltecknet. Detta sker utan att JVM eller kompilatorn klagar. Ibland då man använder denna typ av konvertering försvinner information utan att man har tänkt på det:
class TestDataLoss{
public static void main(String[] args){
int i=257;
byte b=(byte) i;
i=(int) b;
System.out.println("i="+i);
}
}
|
När vi kör programmet händer följande:
[olle@dev1]$ java TestDataLoss
i=1
|
Anledningen till dataförlusten är att talet 257 är större än 127 som är det största tal byte kan innehålla. Tänker man binärt har 257 den nionde biten satt till ett. Då int konverteras till en byte försvinner alla bitar utom de 8 minst signifikanta. Detta blir lättare att se om vi skriver ut bitarna:
class TestDataLoss2{
public static void main(String[] args){
int i=257;
System.out.println("i binary="+Integer.toBinaryString(i));
byte b=(byte) i;
System.out.println("b binary="+Integer.toBinaryString(b));
i=(int) b;
System.out.println("i binary="+Integer.toBinaryString(i));
System.out.println("i="+i);
}
}
|
Vi testkör programmet och får:
[olle@dev1]$ java TestDataLoss2
i binary=100000001
b binary=1
i binary=1
i=1
|
5. Implicit konvertering
Genomgående i Java är det alltid går att implicit konvertera till en typ med större räckvidd (fler bitar), en så kallad breddande konvertering. Dessa är reglerna för tillåtna implicita breddande konverteringar:
- Heltal kan implicit breddas till ett annat heltal med större räckvidd.
- Heltal kan implicit breddas till float.
- float kan implicit breddas till double.
- Ingenting kan implicit konverteras till char, eftersom andra typer kan vara negativa, men char kan implicit breddas till int eller större.
Då man breddar ett heltal förlängs den mest signifikanta biten så att den fyller upp alla nya bitar. Här går ingen information förlorad, men då man breddar ett heltal till ett flyttal kan information i de minst signifikanta bitarna försvinna. Nedan ges ett exempel på implicita breddningar:
class TestConvert{
static void foo(float f){
System.out.println("foo f="+f);
}
public static void main(String[] args){
byte b=17;
short s=b;
int i=s;
long l=i;
foo(l);
float f=l;
double d=f;
char c=12;
i=c; //char to int
f=2; //int to float
d=2; //int to double
}
}
|
Vi kör programmet:
[olle@dev1]$ java TestConvert
foo f=17.0
|
6. Speciella implicita konverteringar
När man initierar en primitiv typ med en litterär görs ofta konverteringar som normalt inte är tillåtna. Det är för att kompilatorn direkt kan avgöra om en konvertering kan ske utan att data förloras. De speciella implicita konverteringar som kan göras är:
- En byte kan initieras med en litterär int.
- En short kan initieras med en litterär int.
- En char kan initieras med en litterär int.
Här kommer ett exempel:
class TestToPrimitive{
public static void main(String[] args){
byte b=17;
char c=117;
System.out.println("c="+c);
}
}
|
Vi kör programmet:
[olle@dev1]$ java TestToPrimitive
c=u
|
När man försöker initiera en typ utanför dess räckvidd får man ett kompileringsfel:
class TestBound{
public static void main(String[] args){
byte b=128;
}
}
|
Vid kompileringen sker följande:
[olle@dev1]$ TestBound.java:3: possible loss of precision
found : int
required: byte
byte b=128;
1 error
|
7. Talbaser
När det gäller heltal används automatiskt talbasen 10, men om man vill kan man specifiera talbasen 16 (hexadecimalt) eller 8 (oktalt).
- Oktala tal= Heltal som börjar med en nolla översätts till basen 8. Hela talet måste bestå av siffror mellan 0 och 7.
- Hexadecimala tal= Tal som börjar med 0x översätts till basen 16. Hela talet måste bestå av "siffror" mellan 0 och F.
Ett exempel:
class TestBase{
public static void main(String[] args){
int okt=010;
int hex=0x10;
System.out.println("okt="+okt);
System.out.println("hex="+hex);
}
}
|
Kör man detta program får man följande resultat:
[olle@dev1]$ java TestBase
okt=8
hex=16
|
8. Char
Eftersom char är ett 16-bitars postivt heltal konverteras minustal till heltal. Klassen TestChar demonstrerar konvertering av negativa heltal till char.
class TestChar{
public static void main(String[] args){
int i=117;
char c=(char) i;
System.out.println("c="+c);
int j=-117;
char d=(char) j;
j= (int) d;
System.out.println("d="+d+" j="+j);
}
}
|
Vid en körning av följande program får vi denna utskrift:
[olle@dev1]$ java TestChar
c=u
d=? j=65419
|
Alltså, -117 konverteras inte till 117 då det blir en char. Om du vill skriva ut W finns det 3 sätt:
class TestChar2{
public static void main(String[] args){
char c1='\u0057';
char c2=(char) 87;
char c3='W';
System.out.println("c1="+c1);
System.out.println("c2="+c2);
System.out.println("c3="+c3);
}
}
|
Vid en körning händer följande:
[olle@dev1]$ java TestChar2
c1=W
c2=W
c3=W
|
Det enklaste sättet att skriva en char är som i c3, att man skriver själva tecknet. Men vissa tecken är lite speciell måste skrivas på följande sätt:
Tecken | | Beskrivning |
\b | | backspace |
\t | | tab |
\n | | newline |
\f | | formfeed |
\r | | carriage return |
\" | | double quotation mark |
\' | | single quotation mark |
\\ | | backslash |
'\uXXXX' | | Ett Unicodetecken. XXXX är hexadecimalt mellan 0000 och FFFF. Detta är det enda sättet att skriva in ett 16 bitars Unicodetecken. |
\XXX | | En char. XXX är oktalt mellan 000 och 377. |