Εισαγωγή στην Java - κεφ. 9

...ασύγχρονα μαθήματα γλώσσας Java

Εισαγωγή στην Java - κεφ. 9

Δημοσίευσηαπό alkismavridis » 01 Φεβ 2013, 02:20

Προηγούμενο: Πίνακες - Πέρασμα ορισμάτων
Επόμενο: Exceptions

Τρεις χρήσιμες κλάσεις


Σκοπός αυτού του κεφαλαίου είναι να γνωρίσουμε αναλυτικότερα τρείς από τις έτοιμες κλάσεις που μας δίνει η Java.


Η Java μας δίνει πολλές έτοιμες κλάσεις για να χρησιμοποιήσουμε. Μερικές από αυτές είναι αναντικατάστατες (δηλαδή δε θα μπορούσαμε να γράψουμε ένα δικό κας κώδικα που να κάνει την ίδια δουλειά), και μερικές άλλες μπορούν να αντικατασταθούν από δικό μας κώδικα.
Το να χρησιμοποιούμε όμως τις έτοιμες κλάσεις της Java αντί να φτιάχνουμε δικιές μας που να κάνουν την ίδια δουλειά έχει τρία βασικά πλεονεκτήματα:

1. Οι κλάσεις αυτές έχουν φτιαχτεί από προγραμματιστές (επιτρέψτε μου να πω) πολύ καλύτερους από εμάς. Άρα έχουν επιμεληθεί λεπτομέρειες που εμείς δεν θα λαμβάναμε υπ' όψιν.
2. Θα ξοδεύαμε πολύ χρόνο για να φτιάξουμε το ίδιο πράγμα που έφτιαξε κάποιος άλλος. Αντικρούει τη βασική φιλοσοφία του αντικειμενοστραφούς προγραμματισμού, το να «χτίζεις βήμα-βήμα» και όχι κάθε φορά από την αρχή. Μόνο για διδακτικούς λόγους έχει νόημα να φτιάχνουμε κάτι που ήδη υπάρχει, ή αν θέλουμε να το βελτιώσουμε.
3. Τις κλάσεις αυτές τις χρησιμοποιούν όλοι οι προγραμματιστές της Java. Αυτό βοηθά πολύ την συνενόηση μεταξύ προγραμματιστών, λύση αποριών κτλ.
Επίσης υπάρχουν εγκατεστημένες σε όλους τους υπολογιστές που έχουν Jvm. Όταν πχ φτιάχνετε ένα πρόγραμμα που χρησιμοποιεί την κλάση Scanner, και θέλετε να πάρετε αυτό το πρόγραμμα σε άλλον υπολογιστή, δε χρειάζεται να πάρετε και την κλάση Scanner μαζί, γιατί απλώς... είστε σίγουροι ότι η Scanner θα υπάρχει και εκεί!! Αν όμως αντί για Scanner φτιάχνατε ένα δικό σας αντικείμενο.. που να κάνει την ίδια δουλειά, στον άλλο υπολογιστή αυτό δε θα υπήρχε! Άρα θα πρέπει να το «κουβαλάτε» μαζί με το κυρίως πρόγραμμα.


Θα επαναλάβω ότι όταν προγραμματίζετε σε Java καλό είναι να έχετε δίπλα σας αυτή την ιστοσελίδα. Περιέχει όλες τις κλάσεις που μας δίνει η Java. Όπως θα παρατηρήσετε είναι πάαααρα πολλές!! Και φυσικά δε χρειάζεται να τις γνωρίζετε όλες, παρά μόνο τις βασικότερες, και αυτές που σας αφορούν περισσότερο.
Τι σας αφορά περισσότερο; Λοιπόν αυτό μόνο η πορεία θα σας το δείξει. Σε κάθε περίπτωση κάθε αντικείμενο που θα συναντήσετε, έχει την περιγραφή του στην παραπάνω ιστοσελίδα (επιπσης όλα τα links που θα παραθέσω παρακάτω ξεκινούν από αυτήν).

Για κάθε μία από τις κλάσεις που θα βλέπουμε, θα αναλύουμε τις πιο χρήσιμες μεθόδους της. Αν θεωρείτε ότι κάποια από αυτές δε σας αφορά, παρακάμψτε την αντίστοιχη παράγραφο, και συνεχίστε. :-)


1. Object
Ας αρχίσουμε από την κλάση Object, τη βασική κλάση της Java.
Σε αυτή θα βρούμε πολλές χρήσιμες μεθόδους τις οποίες όλα τα αντικείμενα έχουν, αφού όλα τα αντικείμενα είναι και Object :-)
Αναλυτική περιγραφή της κλάσης θα βρείτε εδώ.
Προς το παρόν θα κρατήσουμε την μέθοδο equals και την getClass, αλλά έχετε κατά νου ότι όσο πιο πολλά θα μαθαίνουμε για την Java, τόσο πιο πολύ θα καταλαβαίνουμε πόσο χρήσιμες είναι οι μέθοδοι αυτής τηνς κλάσης.


1.1 equals
Η equals όπως έχουμε πει παίρνει όρισμα ένα Object (δηλαδή οποιδήποτε αντικείμενο) και επιστρέφει μία boolean η οποία είναι true μόνο αν τα δύο αντικείμενα έχουν ίδιες τιμές.
Η διαφορά της equals από τον τελεστή == για αντικείμενα είναι ότι η equals μπορεί να δώσει true ακόμα και αν τα αντικείμενα δεν ταυτίζονται, αρκεί να έχουν την ίδια τιμή. Αντίθετα ο τελεστής == για τα αντικείμενα επιστρέφει true μόνο αν οι δύο μεταβλητές αναφέρονται στο ίδιο αντικείμενο.
Έτσι η κάθε μία έχει τη ξεχωριστή χρησιμότητά της...


1.2 getClass
Η getClass δεν έχει ορίσματα, και επιστρέφει ένα αντικείμενο Class που μας λέει την κλάση του αντικειμένου. (οκ, το ότι είναι Object το ξέρουμε, αλλά τί άλλο είναι;)

Αναλυτική περιγραφή την κλάσης Class μπορείτε να βρείτε εδώ. Όπως θα διαπιστώσετε η κλάση αυτή έχει πάρα πολλές μεθόδους που μας δίνουν όποια πληροφορία θέλουμε για την κλάση! Προς το παρόν όμως το μόνο που μας ενδιαφέρει είναι η μέθοδος getName() που επιστρέφει ένα String με το όνομα της κλάσης!
Δείτε το ακόλουθο παράδειγμα:
Μορφοποιημένος Κώδικας: Επιλογή όλων
//Αρχείο ClassTest.java
public class ClassTest {

static void sayWhatYouAre(Object ob) {

if (ob==null)
{System.out.print("Είμαι ένα κενό αντικείμενο. Προς το παρόν δεν είμαι τίποτα...\n"); return;}


String str = ob.getClass().getName();

if (str.equals("java.util.Scanner"))
System.out.print("Είμαι ένα Scanner. Δουλειά μου είναι να διαβάζω String από το χρήστη και από αρχεία.\n");

else if (str.equals("java.lang.String"))
System.out.print("Είμαι ένα String. Δουλειά μου είναι να κρατάω ένα κείμενο χαρακτήρων.\n");

else if (str.equals("java.lang.Object"))
System.out.print("Είμαι ένα Object. Όλα τα αντικείμενα είναι Object. "+
"Αν ένα αντικείμενο σας πει ότι δεν είναι Object, σας λέει ψέματα!!\n");

}//sayWhatYouAre


public static void main (String args[]) {
Object ob1, ob2=null;
String str = "A String";
java.util.Scanner sc;

ob1 = new Object(); //αρχικοποιούμε το ob1. Το ob2 παραμένει null...
sc = new java.util.Scanner(System.in);

System.out.print("\n\n");
sayWhatYouAre(ob1);
sayWhatYouAre(sc);
sayWhatYouAre(str);
sayWhatYouAre(ob2);
System.out.print("\n\n");
}//main
}//class



2. System
Ας πάμε τώρα στην κλάση System. Αναλυτική περιγραφή βρίσκουμε εδώ.
Στην κλάση αυτή θα βρούμε πολύ χρήσιμες static μεθόδους:

2.1 System.arraycopy
static void arraycopy(Object src, int srcpos, Object dest, int destpos, int len)

Αντιγράφει τα στοιχεία ενός πίνακα (του src) σε έναν άλλο (τον dest). Το srcpos λέει από ποιό στοιχείο του src θα αρχίσει να αντιγράφει. Το destpos λέει σε ποιό σημείο του dest θα αρχίσει να αντιγράφει. Τέλος, το len λέει πόσα στοιχεία θα αντιγράψει.
Μη σας παραξενεύει το ότι ο τύπος των πινάκων είναι Object, χωρίς να βλέπετε πουθενά αγκύλες, και οι πίνακες απλά Object είναι!!

Πολύ συχνά θα συμβαίνει ότι θα θέλουμε να αντιγράψουμε ολόκληρο τον πίνακα σε έναν άλλο. Αυτό θα γινόταν πχ με τις εντολές:
Μορφοποιημένος Κώδικας: Επιλογή όλων
System.arraycopy(arr1,0, arr2, 0, arr1.length);


Γενικά τη δουλειά που κάνει η arraycopy μπορούμε να την κανουμε και «χειροκίνητα» μέσα σε μία εντολή for. Συνήσταται όμως η χρήση της arraycopy για τρείς λόγους:

1. Δεν υπάρχει κανένας λόγος να κάνουμε μία δουλειά με περισσότερο γράψιμο, όταν μπορούμε να την κάνουμε με λιγώτερο.
2. Κάνουμε πιο ευανάγνωστο κώδικα, και πιο εύκολα τροποποιήσιμο.
3. Η arraycopy κάνει τη δουλειά πιο γρήγορα από ότι ο δικός μας κώδικας.


2.2 System.exit
static void exit(int status)

Τερματίζει το Virtual Machine, το οποίο δίνει κατάσταση επιστροφής την τιμή status.
Πρακτικά αυτό σημαίνει ότι αυτή η εντολή τερματίζει ακαριαία το πρόγραμμά μας.

Όμως αφού τερματίζει, τι μας ενδιαφέρει η τιμή του status; Τι νόημα έχει;
Για την εφαρμογή μας το status δεν παίζει κανένα ρόλο, αφού δε θα «ζήσει» για να καταλάβει τη διαφορά. Απασχολεί όμως το λειτουργικό μας σύστημα! Γιατί το status επιστροφής μας μπορεί να το χρησιμοποιήσει το λειτουργικό σύστημα για να αποφασίσει τι θα κάνει μετά.

Ήθισται να δίνουμε status επιστροφής 0 όταν «όλα πήγαν καλά», ενώ 1 όταν «κάτι πήγε στραβά».


2.3 System.lineSeparator
static String lineSeparator()

Επιστρέφει το χαρακτήρα (ή τους χαρακτήρες) για αλλαγή παραγράφου.

Για λειτουργικά συστήματα όπως Linux ή Unix ο χαρακτήρας αυτός είναι "\n" ενώ στα Windows (των οποίων ο μόνος σκοπός ύπαρξης είναι να μας κάνουν τη ζωή δύσκολη) είναι "\r\n", δηλαδή δύο χαρακτήρες στη σειρά.

Αν πιστεύετε ότι το πρόγραμμά σας θα τρέξει και σε Windows, μπορείτε να κάνετε κάτι σαν αυτό:
Μορφοποιημένος Κώδικας: Επιλογή όλων
final static String ln = System.lineSeparator();

//...
//...
//...

System.out.print("Γεια σας"+ln);
//αντί για
System.out.print("Γειά σας\n");

Αν και για τύπωμα στην οθόνη, το \n δουλεύει και στα Windows, άρα η χρήση του lineSeparator έχει νόημα περισσότερο όταν διαβάζουμε/γράφουμε σε αρχεία.



2.4 System.nanoTime
static long nanoTime()

Επιστρέφει σε nanosecond πόσο χρόνο δουλεύει το Virtual Machine.
Αυτό συνήθως δε μας ενδιαφέρει τόσο, όσο η διαφορά δύο τέτοιων μετρήσεων. Ας δούμε δύο παραδείγματα:
Μορφοποιημένος Κώδικας: Επιλογή όλων
long l1, l2;

l1 = System.nanoTime();
// «Κώδικας»
l2 = System.nanoTime();

// τώρα η διαφορά l2-l1 μας λέει πόση ώρα (σε nSec) έκανε το pc μας να εκτελέσει το ενδιάμεσο «Κώδικας»
System.out.print( "Χρόνος: "+ ((l2-l1)/1000000000) + "δευτερόλεπτα.\n);
//φυσικά η διαίρεση με το 1000000000 είναι για να το μετατρέψουμε σε δευτερόλεπτα

Μορφοποιημένος Κώδικας: Επιλογή όλων
//αρχείο QuickAnswer.java

import java.util.Scanner;

public class QuickAnswer {

public static void main(String args[]) {
long l1, l2;
int sec;
String answer;
Scanner sc = new Scanner(System.in);

System.out.print("Πρέπει να απαντήσεις σε 5 δευτερόλεπτα! Δώστε οποιοδήποτε χαρακτήρα για να ξεκινήσετε...\n");
answer = sc.next();

System.out.print("Πόσο κάνει 11*12; ");
l1 = System.nanoTime();
answer = sc.next();
l2 = System.nanoTime();
sec = (int) ( (l2-l1)/1000000000 );

if (!answer.equals("132"))
System.out.print("Λάθος απάντηση! Χάσατε...\n");

else if (answer.equals("132") && sec<=5)
System.out.print("Συγχαρητήρια!! Νικήσατε!! Κάνατε μόνο "+sec+" δευτετόλεπτα...\n");

else
System.out.print("Σωστή απάντηση, αλλά αργή. Κάνατε "+sec+" δευτερόλεπτα... Χάσατε.\n");
}//main

}//class




3. String
Εδώ έχουμε πολλά χρήσιμα να δούμε. Είναι σημαντικό να μάθουμε να δουλεύουμε με τα String γιατί αυτή είναι η κύρια πηγή αλληλεπίδρασης με το χρήστη. Αναλυτική περιγραφή υπάρχει εδώ.
Ας δούμε τι δυνατότητες έχουμε:


3.1 String Constructors
Όπως θα έχετε παρατηρήσει, δεν έχουμε χρησιμοποιήσει ποτέ Constructor για να δημιουργήσουμε ένα String. Απλώς ανοίγουμε διπλά εισαγωγικά και αυτό ήταν! Αυτό όμως δε σημαίνει ότι δεν υπάρχουν Constructors στην κλάση String. Κάθε άλλο! Όπως θα δείτε στην παραπάνω ιστοσελίδα, υπάρχουν πολλοί! Το ότι δημιουργούμε String χωρίς να καλούμε τους Constructors, είναι μία «ευκολία» που η Java δίνει ειδικά και μόνο για τα String.

Προς το παρόν θα μελετήσουμε ένα από τους Constructor:
Μορφοποιημένος Κώδικας: Επιλογή όλων
String (char[] text)


Αυτό που κάνει είναι να δημιουργεί ένα String που περιέχει όλους τους χαρακτήρες του πίνακα text.
Για παράδειγμα:
Μορφοποιημένος Κώδικας: Επιλογή όλων
char ch[] = new char[] {'έ', 'ν', 'α', '_', 'κ', 'ε', 'ί', 'μ', 'ε', 'ν', 'ο', '\n'};
String str = new String(ch);
System.out.print(str);



3.2 toCharArray
char[] toCharArray()

Αυτή η μέθοδος μπορεί να συνδιαστεί τέλεια με τον Constructor που είδαμε πιο πάνω!
Κάνει ακριβώς το αντίθετο από αυτόν, επιστρέφει ένα char[] με στοιχεία τους χαρακτήρες του String.
Κρατώντας ένα τέτοιο πίνακα μπορούμε να κάνουμε ό,τι αλλαγές θέλουμε (ένα-ένα χαρακτήρα) και ύστερα να ξαναδημιουργήσουμε ένα String! Ας δούμε:
Μορφοποιημένος Κώδικας: Επιλογή όλων
String s1 = "Χαίρε!\n";

//Ας υποθέσουμε ότι δε μας αρέσει το "\n" στο τέλος, και θέλουμε να το βγάλουμε:
char[] ch = s1.toCharArray();
ch[ch.length-1] = \u0000'; //Αλλάζουμε τον τελευταίο χαρακτήρα στον «κενό» χαρακτήρα με τιμή 0000.
s1 = new String(ch); //Αυτό ήταν!



3.3 charAt
char charAt(int index)

Ας πούμε ότι θέλουμε να ελέγξουμε μόνο ένα χαρακτήρα από το String. Αυτό μπορεί να γίνει εύκολα με αυτή τη μέθοδο, η οποία επιστρέφει απλώς το χαρακτήρα στη θέση index (ο πρώτος χαρακτήρας είναι ο υπ' αριθμόν 0). Πχ για να δούμε αν το String str ξεκινά με 's' γράφουμε:
Μορφοποιημένος Κώδικας: Επιλογή όλων
if (str.charAt(0) == 's') //...



3.4 length
int length()

Επιστρέφει το μήκος του String. Πχ αν έχουμε διαβάσει/δημιουργήσει ένα String str:
Μορφοποιημένος Κώδικας: Επιλογή όλων
int l = str.length();

if (l<10) System.out.print("Το κείμενό σου είναι μικρό.\n");
else if (l<40) System.out.print("Το κείμενό σου είναι μεσαίου μεγέθους.\n");
else System.out.print("Το κείμενό σου είναι μεγάααααλο!!!\n");



3.4 startsWith και endsWith
boolean startsWith(String otherString)
boolean startsWith(String otherString, int index)

boolean endsWith(String otherString)

Αυτές οι μέθοδοι μας λένε εάν το String μας αρχίζει με το otherString, ή αν τελειώνει με αυτό.
Πχ αν s1 = "Alkis Mavridis", και s2 = "Al", η
Μορφοποιημένος Κώδικας: Επιλογή όλων
s1.startsWith(s2)
θα δώσει true, όπως και η
Μορφοποιημένος Κώδικας: Επιλογή όλων
s1.endsWith("s")


Η έκδοση της starsWith με το ένα παραπάνω όρισμα, μας λέει αν το String μας, μετρούμενο από τη θέση index «αρχίζει» με το otherString. Πχ το
Μορφοποιημένος Κώδικας: Επιλογή όλων
s1.startsWith("ki",2)
θα δώσει true.



3.5 substring
String substring(int begin)
String substring(int begin, int end)

Αυτή η μέθοδος (ας δούμε την έκδοση με τα δύο ορίσματα) επιστρέφει ένα μέρος μόνο του String μας, αρχίζοντας από κάπου, και τελειώνοντας κάπου.
Στην έκδοση με το ένα όρισμα, αρχίζει από κάπου και συνεχίζει μέχρι το τέλος. Πχ αν s1 = "This is a String", η εντολή:
Μορφοποιημένος Κώδικας: Επιλογή όλων
String s2 = s1.subString(8);
θα δώσει στο s2 την τιμή "a String", ενώ η
Μορφοποιημένος Κώδικας: Επιλογή όλων
String s2 = s1.subString(1,3);
θα δώσει την τιμή "his".
Σε αυτές τις περιπτώσεις το s1 μένει ανέπαφο. Μη νομίζετε δηλαδή ότι αυτές οι μέθοδοι «κόβουν» το String μας! Αν παρ' όλα αυτά θέλετε να «κόψετε» το String, απλώς βάλτε στη θέση του s2... πάλι το s1, και έχετε το επιθυμιτό αποτέλεσμα! πχ:
Μορφοποιημένος Κώδικας: Επιλογή όλων
s1 = s1.subString(0,8);//τώρα το s1 έγινε "This is a"...




3.6 toLowerCase και toUpperCase
String toLowerCase()
String toUpperCase()

Αυτές οι δύο μέθοδοι επιστρέφουν το String μας, αλλά κάνουν όλους τους χαρακτήρες είτε καφαλαίους είτε μικρούς.
Πχ αν s1 = "This is a String", και:
Μορφοποιημένος Κώδικας: Επιλογή όλων
String s2 = s1.toLowerCase();
String s3 = "This is an other String".toUpperCase(); //παρατηρήστε τη χρήση της τελείας εδώ!!
τότε το s2 θα είναι "this is a string", και το s3 θα είναι "THIS IS AN OTHER STRING".



3.7 compareTo και compareToIgnoreCase
int compareTo (String other)
int compareToIgnoreCase (String other)

Πολύ χρήσιμες μέθοδοι αν θέλουμε να οργανώσουμε Strings σε αλφαβητική σειρά.
Η πρώτη επιστρέφει αρνητικό αριθμό αν το String που καλεί την μέθοδο αυτή προηγείται αλφαβητικά από το other, ένα θετικό αριθμό αν έπαιται, και μηδέν αν τα String είναι ίδια.
Η δεύτερη κάνει το ίδιο, αλλά δε λαμβάνει υπ' όψιν της διαφορές πεζών-κεφαλαίων.



3.8 isEmpty
boolean isEmpty()

Επιστρέφει true αν το String που την καλεί είναι το "". Δηλαδή δεν περιέχει κανένα χαρακτήρα.
Το κενό διάστημα πιάνεται για χαρακτήρας, άρα το " ".isEmpty() είναι false.



3.9 replace
String replace (char oldchar, char with)

Αντικαθιστά όλους τους χαρακτήρες που θα βρεί ίσους με oldchar, μς την τιμή with.
Πχ το "his".replace('i', 'a') θα δώσει την τιμή "has".
Την συνάρτηση αυτή μπορείτε να την καλέσετε και με δύο String!! (το πως γίνεται αυτό θα το καταλάβετε όταν μιλήσουμε για interfaces)


3.10 split
String[] split(String regex)

Επιστρέφει ένα πίνακα από String. Ο πίνακας αυτός περιέχει το String που κάλεσε τη μέθοδο... σε κομμάτια.
Το όρισμα regex λέει πως θα χωριστούν τα κομμάτια, ή να το διατυπώσουμε πιο σωστά, ποιό κείμενο θα χωρίζει τα κομμάτια.

Για παράδειγμα ο κώδικας
Μορφοποιημένος Κώδικας: Επιλογή όλων
String str = "Το κείμενο που θα χωριστεί σε κομμάτια";
String[] array = str.split(" ");
θα δημιουργήσει τον εξής πίνακα:
Μορφοποιημένος Κώδικας: Επιλογή όλων
array = new String[] { "Το", "κείμενο", "που", "θα", "χωριστεί", "σε", "κομμάτια" };
Γιατί καλέσαμε την μέθοδο split με όρισμα το κενό διάστημα. Άρα όπου συναντούσε κενό διάστημα, χώριζε και το κομμάτι από το προηγούμενό του!


Προηγούμενο: Πίνακες - Πέρασμα ορισμάτων
Επόμενο: Exceptions

Creative Commons License
Η εργασία υπάγεται στην άδεια Creative Commons Αναφορά-Παρόμοια διανομή 3.0 Ελλάδα
Γνώσεις ⇛ Linux: Μέτριο┃ Προγραμματισμός: Java, Assembly, Fortran, μαθαίνω C/X11┃ Αγγλικά: Μέτρια
Λειτουργικό σε Η/Υ ϰ μοντέλο: Ubuntu 14.04 64-bit ┃ Τρόπος εγκατάστασης: Live USB
Προδιαγραφές ⇛ Desktop: Intel i5 2320 3.00GHz.┃ MotherBoard: Asus p8h61 -m pro
Προδιαγραφές ⇛ RAM: 4GB ┃ Τροφοδοτικό Corsair CX430

GPU: Intel 2nd Generation Core Processor Family Integrated Graphics Controller [8086:0102] {i915}
5 eth0: Realtek RTL8111/8168B PCI Express Gigabit Ethernet controller [10ec:8168] (rev 06) ⋮ wlan0: 0b05:1723 ASUS WL-167G v2 802.11g Adapter [Ralink RT2571W]
Οθόνη Schaub Lorenz (Tv)
alkismavridis
punkTUX
punkTUX
 
Δημοσιεύσεις: 273
Εγγραφή: 18 Μαρ 2009, 18:46
Εκτύπωση

  • ΣΧΕΤΙΚΑ ΘΕΜΑΤΑ
    ΑΠΑΝΤΗΣΕΙΣ
    ΠΡΟΒΟΛΕΣ
    ΣΥΓΓΡΑΦΕΑΣ

Επιστροφή στο Μαθήματα Java

cron