Java Hellenic User Group logo

Αρχική Σελίδα
Αγορά Συζήτησης
Κείμενα/Βοηθήματα

Valid CSS!

Πρωτογενείς τύποι δεδομένων

Εισαγωγή

Ένας από τους λόγους που η Java θεωρητικά δεν είναι μια 100% αντικειμενοστραφής γλώσσα είναι η παρουσία και σε αυτήν, των λεγόμενων πρωτογενών τύπων δεδομένων (primitive data types ή build-in data types. Όταν μιλάμε για αρχέγονους τύπους δεδομένων εννοούμε τους γνωστούς μας ακεραιους, δεκαδικους, χαρακτηρες και byte και κάθε ένας από αυτούς χρησιμοποιείται για να αποθηκεύσουμε στη μνήμη μια αλφαριθμητική τιμή, αλλά για να τους χρησιμοποιήσουμε δεν χρειάζεται η δημιουργία κάποιου object μέσω αντιστοίχου class κατασκευαστή (constructor). Αλλά ας ξεκινήσουμε με τα βασικά! Η παρακάτω παράγραφος περιληπτικά δίνει την εικόνα των bit και byte (γνωστά και ως οκτάδες - octets) για όσους δεν έχουν προηγούμενη εμπειρία!

Bits και bytes

Όπως όλοι ξέρουμε τα μοναδικά πράγματα τα οποία καταλαβαίνει ο επεξεργαστής του υπολογιστή μας είναι το 0 και το 1. Ο,τιδήποτε κάνουμε, δημιουργούμε ή αποθηκεύουμε στον υπολογιστή μας καταλήγει σε μεγάλες αλληλουχίες 0 και 1 τις οποίες και επεξεργαστής διαχειρίζεται. Τι είναι το bit και τι το byte; Φανταστείτε το bit σαν την ελάχιστη οντότητα πληροφορίας που μπορεί να διαχειριστεί ο υπολογιστής. Το bit μπορεί να πάρει μόνο μια τιμή και αύτη η τιμή μπορεί να είναι το 0 ή το 1. Το byte αντίστοιχα αποτελείται από 8 bit (εξ' ου και η ονομασία οκτάδα). Μια αλληλουχία 8 bit τα οποία μπορούν όπως είπαμε να έχουν την τιμή 0 η 1. Παρακατω δίνω ένα σχηματικό παράδειγμα του byte.

Byte

0

0

1

0

1

0

0

1

 bit 8            bit 7            bit 6           bit 5         bit 4          bit  3          bit  2          bit  1               

Βλέπουμε λοιπόν το byte έχει 8 bit από τα οποία μερικά έχουν την τιμή ένα και αλλά την τιμή μηδέν. Δεν πρέπει να ξεχνάμε ότι ο υπολογιστής καταλαβαίνει μόνο το δυαδικό σύστημα. Και ότι η κάθε ενέργεια μας μεταφράζεται σε αλληλουχίες αριθμών του δυαδικού συστήματος!

Βασικοί τύποι στην Java

Η Java υποστηρίζει όλους τους βασικούς τύπους που μπορούμε να συναντήσουμε και σε άλλες γλώσσες και έχει το προνόμιο ότι οι βασικοί τις τύποι είναι συμβατοί και έχουν την ίδια χωρητικότητα πληροφορίας ανεξάρτητα ποια πλατφόρμα υπολογιστή χρησιμοποιούμε, αρκεί το εν λόγω σύστημα να έχει υποστήριξη Java (ανάλογο virtual machine)! Οι χρηστές της C και C++ πολλές φορές ήταν υποχρεωμένοι να γράφουν κομμάτια του κώδικα τους για προγράμματα που ήθελαν να τρέχουν σε πλατφόρμες, αυτό γιατί σε κάθε τέτοια πλατφόρμα οι τύποι δεδομένων κατέχουν διαφορετική ποσότητα μνήμης. Παραδείγματος χάρη μπορούσε στην Α πλατφόρμα ο τύπος του ακέραιου να κατείχε 8 byte μνήμης ενώ στην B πλατφόρμα 4 byte μνήμης. Ας δούμε με περισσότεροι λεπτομέρεια όλους τους αρχέγονους τύπους στον παρακάτω πίνακα.

Πρέπει να τονίσουμε σε αυτό το σημείο ότι οι βασικοί τύποι στην Java είναι signed δηλαδή, περιέχουν μέσα στην δομή τους και την πληροφορία για το πρόσημο τους. Αυτή η πληροφορία βρίσκεται στο πιο αριστερό bit της τιμής της μεταβλητής. Ένα απλό παράδειγα ο τύπος byte στη Java μπορεί να αποθηκεύσει πληροφορία 8 bit (βλέπε πάνω σχήμα), η τιμή του (bit 8) δηλώνει αν η μεταβλητή περιέχει έναν θετικό η αρνητικό αριθμό.

Π.χ. η τιμή 6 μεταβλητής τύπου (byte) αναπαρίσταται για τον υπολογιστή μας έτσι

0

0

0

0

0

1

1

0

  bit 8             bit 7          bit 6          bit 5           bit 4             bit 3           bit 2          bit 1

Η τιμή όμως (-6) της μεταβλητής τύπου (byte) αναπαρίσταται για τον υπολογιστή μας

1

0

0

0

0

1

1

0

bit 8            bit 7            bit 6            bit  5         bit 4            bit  3          bit 2          bit 1

To πιο αριστερό bit 8 που δηλώνει το πρόσημο στην περίπτωση του -6 έχει την τιμή 1 και δηλώνει την ύπαρξη αρνητικού πρόσημου. Γι' αυτό το λόγο θα παρατηρήσουμε ότι σε έναν τύπο η μέγιστη αρνητική τιμή είναι κατά ένα πιο μεγάλη αριθμητικά από την μέγιστη θετική τιμη. Δείτε το πεδίο τιμών του τύπου byte.

Πίνακας 1

Τύπος

Μέγεθος σε bit

Πεδίο τιμών

boolean

8

true ή false

byte

8

-128 έως +127

char

16

\u0000 έως \uFFFF

short

16

-32,768 έως 32,767

int

32

-2,147,483,648 έως +2,147,483,647

long

64

-(2^63) έως +(2^63)+1

float

32

-3.4028234663852886E+38 έως

-1.40129846432481707e-45

double

64

Αρνητικές τιμές

-1.79769313482623157Ε+308 έως -4.94065645841246544e-324

 

Θετικές τιμές

4.94065645841246544e-324

έως

1.79769313482623157Ε+308

 

Ας δούμε όμως πως χρησιμοποιούμε τους τύπους αυτούς για να δημιουργήσουμε και να χειριστούμε μεταβλητές.

Πως θέτουμε και χρησιμοποιούμε μεταβλητές αρχέγονων τύπων (declaring primitive type variables)

Εδώ θα χρησιμοποιήσουμε μια νέα κλάση που θα την ονομάσουμε aSimpleClass. Η συγκεκριμένη κλάση δεν έχει main μέθοδο άρα δεν θεωρείται Java εφαρμογή! Παρόλα αυτά μπορούμε να διακρίνουμε την δήλωση σε επίπεδο κλάσης διάφορων μεταβλητών αλλά και τη δήλωση διάφορων μεθόδων οι οποίες παίρνουν ως όρισμα αντίστοιχα ορισμένες μεταβλητές. Ας τα δούμε με περισσότερη λεπτομέρεια! Μετά τη δήλωση της κλάση μας (aSimpleClass) ακολουθούν 7 δηλώσεις διάφορων μεταβλητών. Ο τρόπος της δήλωσης είναι συγκεκριμένος και πρέπει να ακολουθεί κάποιους κανόνες. Πρώτα πρέπει πάντα τα δηλώνουμε τον τύπο της μεταβλητής (int, long κτλ), στη συνεχεία ένα όνομα και μετά αν θέλουμε μπορούμε να της δώσουμε και μια τιμή! Όπως είπα αν θέλουμε μπορούμε να της δώσουμε τιμή γιατί όπως βλέπουμε στις δηλώσεις μας στην παρακάτω κλάση έχουμε δηλώσει ορισμένες μεταβλητές χωρίς να τις έχουμε δώσει κάποια αρχική τιμή (variables not initialized).

Ένα άλλο χαρακτηριστικό στις παρακάτω 6 δηλώσεις των μεταβλητών αυτών είναι ότι είναι δηλωμένες στο λεγόμενο επίπεδο της κλάσης. Δηλαδή είναι ορατές και προσβάσιμες σε κάθε μέθοδο της κλάσης αλλά και άλλων κλάσεων ανάλογα με τη δημοσιότητα που της έχουμε δώσει στην δήλωση μας. Τι εννοούμε με τον όρο δημοσιότητα όπως έχουμε αναφέρει και σε προηγούμενο κείμενο μια κλάση, μια μέθοδος αλλά και ακόμα μια μεταβλητή μπορεί να χαρακτηριστεί κατά την δήλωση της για το αν θα φαίνεται στον έξω κόσμο που χρησιμοποιεί την κλάση, αν θα φαίνεται σε άλλες κλάσεις που χρησιμοποιούν την κλάση αυτή αλλά και ποια μέρη της θα είναι ορατά! Στη συγκεκριμένη περίπτωση όλες οι μεταβλητές (εκτός μίας) που έχουμε δηλώσει έχουν χαρακτηριστεί ως public (δημόσιες) άρα κάθε ένας που χρησιμοποιεί ένα αντικείμενο της κλάσης aSimpleClass θα μπορεί να χρησιμοποιεί της μεταβλητές αυτές! Αντίθετα η μεταβλητή με όνομα anPrivateInt έχει χαρακτηριστεί private και δεν θα είναι ορατή σε άλλες κλάσεις που χρησιμοποιούν το παράδειγμα μας, πάντως δεν παύει να είναι διαθέσιμη σε όλες τις μεθόδους της κλάσης μας.

Ένα πολύ σημαντικό σημείο που πρέπει να τονιστεί εδώ είναι το εξής. Στην Java (και όχι μόνο) ΑΠΑΓΟΡΕΥΕΤΑΙ να χρησιμοποιήσεις μεταβλητή προτού της έχεις δώσει αρχική τιμή, δειτε το παρακάτω μικρό παράδειγμα μια μεθόδου

public int myMeth (){

int anInt; //δήλωση μεταβλητής με όνομα anInt της οποίας δεν δίνεται αρχική τιμή.

int anInt2=5; //δήλωση μεταβλητής με όνομα anInt2 ,δίνεται αρχική τιμή 5.

int result; //δήλωση μεταβλητής με όνομα result της οποίας δεν δίνεται αρχική τιμή.        

//προσθέτουμε τις μεταβλητές anInt ,anInt2 και δίνουμε αρχική τιμή στην μεταβλητή result

result = anInt +anInt2 ;

return result;

}


Ο compiler με το που επιχειρήσουμε να κάνουμε compile την παραπάνω μέθοδο μέσα σε κάποια κλάση θα παραπονεθεί έντονα γιατί προσπαθούμε στον κώδικα μας να χρησιμοποιήσουμε την μεταβλητή anInt ενώ δεν της έχουμε δώσει κάποια αρχική τιμή!

Συνεχίζοντας στην περιπλάνηση μας μέσα στην κλάση (aSimpleClass) βλέπουμε μετά τη δήλωση των μεταβλητών επιπέδου κλάσης (ή instance variables ή class variables) ακολουθούν 2 δηλώσεις μεθόδων. Η πρώτη (Ameth) δέχεται ως παράμετρο έναν ακέραιο στην συνεχεία τον μετατρέπει σε long (μεγάλος ακέραιος) και τον επιστρέφει. Ο σκοπός αυτής της μεθόδου είναι να μας δείξει πως μπορούμε να κάνουμε αλλαγές στον τύπο μια μεταβλητής. Στη συγκεκριμένη μέθοδο αφού θέλαμε να επιστρέψουμε μια τιμή τύπου long και η παράμετρος μας ήταν τύπου int έπρεπε να βρούμε τρόπο να αλλάξουμε τον τύπο της μεταβλητής σε αυτόν που όριζε η μέθοδος. Η διαδικασία αυτή ονομάζεται type-casting (= αλλαγή ή μασκάρεμα τύπου). Όπως βλέπουμε στην μέθοδο αυτό μπορούμε να το πετύχουμε με το να προσθέσουμε μέσα σε παρένθεση τον τύπο που θέλουμε η αλλαγή να γίνει. Aκόμα πιο προσεκτικά βλέπουμε ότι η μέθοδος στην πρώτη γραμμή της δηλώνει μια μεταβλητή του τύπου (long) και της δίνει αμέσως την τιμή της παραμέτρου αφού όμως πρώτα την μετατρέψει στον ίδιο τύπο. Σε αυτό το σημείο πρέπει να πούμε ότι πρέπει να είμαστε πολύ προσεκτικοί γιατί, είναι λογικό δεν μπορούμε να κάνουμε αλλαγές (type-casting) από οποιονδήποτε τύπο σε οποιονδήποτε άλλο τύπο. Το γιατί θα μας το δείξει ο πίνακας 1.

Παρατηρούμε ότι ο κάθε τύπος μεταβλητής μπορεί να κρατήσει να αποθήκευσει ορισμένη ποσότητα πληροφορίας. Όταν παραδείγματος χάρη δηλώνουμε μια μεταβλητή με τύπο int ξέρουμε από την αρχή ότι η μεταβλητή μας μπορεί να έχει τιμές από -2,147,483,648 έως +2,147,483,647 ούτε παραπάνω ούτε παρακάτω ή αντίστοιχα μια μεταβλητή του τύπου byte μπορεί να πάρει τιμές -128 έως 127. Αν προσπαθήσουμε εμείς να δώσουμε σε μια μεταβλητή τύπου byte την τιμή 345 τότε έχουμε χάσει πολύτιμη πληροφορία γιατί ο υπολογιστή μας έχει δεσμεύσει μνήμη μόνο για συγκεκριμένο εύρος τιμών και όχι παραπάνω. Με την ίδια λογική δεν μπορώ και δεν είναι σωστό να προσπαθήσω να αλλάξω τον τύπο μια μεταβλητής τύπου int σε byte γιατί είναι σχεδόν σίγουρο ότι θα χάσω μέρος της πληροφορίας που κρατάει η μεταβλητή. Ένας μικρός γενικός κανόνας είναι ότι δεν επιχειρούμε σχεδόν ποτέ (type-cast) από τύπο με μεγάλη ποσότητα πληροφορίας σε τύπο με μικρότερη ποσότητα πληροφορίας γιατί είναι πολύ πιθανό να χάσουμε μέρος της πληροφορίας.

Στην επόμενη μέθοδο με όνομα (anotherMeth) ορίζουμε μια μεταβλητή τύπου char (χαρακτήρα) σαν παράμετρο, τοπικά μέσα στην μέθοδο δηλώνουμε και δίνουμε αρχική τιμή σε μια άλλη μεταβλητή με όνομα (aChar2)και δίνουμε και αρχική τιμή τονχαρακτήρα (e). Πρέπει να τονίσουμε ότι η μεταβλητή (char2) έχει ζωή μόνο μέσα στα όρια της μεθόδου, δεν είναι ορατή από κανέναν απ' έξω από την μέθοδο και η ζωή της (scope) έρχεται σε τέλος με το που η μέθοδος ολοκληρώσει την δουλεία της και επιστρέψει αποτέλεσμα.

//aSimpleClass.java η κλάση δεν είναι Java application δεν έχει main μέθοδο
public class aSimpleClass{
public int anInt = 6; //μια δήλωση μεταβλητής ακέραιου
//μια δήλωση μεταβλητής ακέραιου που έχει χαρακτηριστεί private για την κλάση.
private int anPrivateInt = 0;
/*
μια δήλωση πολλαπλων μεταβλητών (ακέραιοι).
Όπως βλέπουμε μπορούμε σε μια γραμμή να δηλώσουμε πολλαπλές
μεταβλητές αρκεί να είναι του ίδιου τύπου
*/
public int aSecInt, aThirdInt;
public boolean aBoolean; //δήλωση μεταβλητής τύπου boolean
public char aChar; //δήλωση μεταβλητής τύπου char (χαρακτήρας)
public char aChar2 =’r’; //δήλωση μεταβλητής char όπου δίνεται και η αρχική τιμή ‘r
public long aLong; //δήλωση μεταβλητής τύπου long

/*
Μια δήλωση μεθόδου που δέχεται σαν παράμετρο έναν
Ακέραιο(anInt) και επιστρέφει έναν ακέραιο συγκεκριμένα τον Αριθμό 5.
*/
public long Ameth(int anInt){
long anotherLong = (long) anInt;
return anotherLong;
}//end of method Ameth
  /**
   *μέθοδος anotherMeth,δεχεται σαν παράμετρο μια μεταβλητή τύπου χαρακτήρα.
   *δηλώνει και ενεργοποιεί με την τιμή 'e' μια ακόμα μεταβλητή τύπου χαρακτήρα
   *Στην συνεχεία δίνει στην παράμετρο aCharParam την τιμή της τοπικής μεταβλητής aChar2 και
   *την επιστρέφει
   */
  public char anotherMeth(char aCharParam)
  {
        char aChar2 ='e'; //δήλωση και αρχικοποίηση τιμής σε μεταβλητή τύπου char.
       
        //θέτουμε την τιμή της παραμέτρου ίση με την τιμή της τοπικής στην μέθοδο μεταβλητή
        aCharParam = aChar2;
       
        //επιστρέφουμε τον χαρακτήρα που θα έχει την τιμή ‘e
        return aCharParam; 
 
   }//end of method
 
   public boolean aBoolMeth(boolean aBoolean)
   {
        //δήλωση και αρχικοποίηση τιμής σε μεταβλητή τύπου boolean
        boolean aBoolean2 = false;                  
       
        //θέτουμε την τιμή στην παράμετρο aBoolean
        aBoolean = true;
       
        //επιστρέφουμε την τιμή true (boolean) όπως ορίζει η δήλωση 
        return true;
   }   
}//end of aSimpleClass class

Να μην ξεχάσουμε να αναφέρουμε τον ιδιαίτερο χαρακτήρα των μεταβλητών τύπου boolean που δεν έχουν αλφαριθμητικό χαρακτήρα και περιορίζονται μόνο στις τιμές true ή false, είναι γνωστές και σαν flags (σημαίες σε ελεύθερη μετάφραση). Βλέπε μέθοδο (aBoolMeth).

Πριν το τέλος

Το παραπάνω κείμενο είναι λογικό να μην καλύπτει 100% όλο το θέμα των βασικών τύπων στην Java. O σκοπός του είναι να αποκτήσουν οι αναγνώστες μια πρώτη επαφή με την διαχείριση και χρησιμοποίηση μεταβλητών αλλά και να κατανοήσουν σε αρχικό στάδιο την έννοια του τύπου και της πληροφορίας. Για αυτή την πρώτη επαφή δεν πρέπει να ξεχάσουμε τα εξής:

  • Για την καλύτερη και πιο σωστή διαχείριση μεταβλητών στα προγράμματά μας είναι καλό να έχουμε της πληροφορίες του πίνακα 1 όπου θα μπορούμε εύκολα και γρήγορα να διαλέγουμε ποιος τύπος μεταβλητής είναι πιο σωστός και χρήσιμος για κάθε ενδεχόμενο
  • ΠΟΤΕ δεν προσπαθούμε να χρησιμοποιήσουμε μεταβλητή πρωτού της έχουμε δώσει αρχική τιμή
  • Eίμαστε πάντα προσεκτικοί σε κάθε προσπάθεια που κάνουμε να αλλάζουμε τον τύπο της μεταβλητής ανάλογα με τις ανάγκες μας, γιατί υπάρχει κίνδυνος να χάσουμε ποσότητα πληροφορίας κατά την διάρκεια της αλλαγής. Ο πίνακας 1 είναι ένας καλός τρόπος και οδηγός για όσους δεν είναι απόλυτα σίγουροι!

Aποστολόπουλος Πάρις
Κωνσταντινίδης Πάνος


  Get Java Now!