Ilias95 Δημοσ. 17 Ιουνίου 2014 Δημοσ. 17 Ιουνίου 2014 Στο παρακάτω snippet: class TestStrings { public static void main(String [] args) { String s1 = "yes"; String s2 = "yes"; String s3 = new String("yes"); if (s1 == s2) System.out.println("s1==s2"); if (s1 == s3) System.out.println("s1==s3"); if (s2 == s3) System.out.println("s2==s3"); } } Θα έχω σαν έξοδο: s1==s2Πράγμα που σημαίνει ότι τα s1 και s2 δείχνουν στο ίδιο αντικείμενο το οποίο είναι διαφορετικό απ' το αντικείμενο στο οποίο δείχνει η s3.Γιατί συμβαίνει αυτό και πως αποφασίζει ο compiler (?) πότε θα δημιουργήσει νέο αντικείμενο και πότε θα χρησιμοποιήσει κάποιο ήδη δημιουργημένο;
defacer Δημοσ. 17 Ιουνίου 2014 Δημοσ. 17 Ιουνίου 2014 Αυτό που βλέπεις είναι αποτέλεσμα του λεγόμενου string interning. To runtime έχει τη δυνατότητα να κρατάει ένα μοναδικό αντίγραφο όποιου string θέλεις και σου την παρέχει μέσω της intern: public String intern() Returns a canonical representation for the string object. A pool of strings, initially empty, is maintained privately by the class String. When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned. It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true. All literal strings and string-valued constant expressions are interned. String literals are defined in section 3.10.5 of the The Java™ Language Specification. Returns: a string that has the same contents as this string, but is guaranteed to be from a pool of unique strings. Ο έλεγχος s1 == s2 βγαίνει true επειδή τα s1 και s2 είναι το ίδιο interned αντίγραφο του "yes" ως literal strings ("All literal strings [..] are interned" -- αυτό απαντάει την ερώτησή σου "πώς αποφασίζει ο compiler"). To s3 επειδή δεν είναι literal αλλά το δημιουργείς επιτόπου με εσκεμμένη κλήση του string constructor είναι διαφορετικό αντίγραφο και άρα όχι ίσο με τα άλλα δύο. Όμως παρόλα αυτά, s1.intern() == s2.intern() == s3.intern() όπως βέβαια και s1 == s1.intern() == s2 == s2.intern() αφού όπως είπαμε τα s1, s2 είναι ήδη interned. 2
Ilias95 Δημοσ. 17 Ιουνίου 2014 Μέλος Δημοσ. 17 Ιουνίου 2014 Αυτό το pool of strings δηλαδή θα διατηρήσει όλα τα string literals που θα δημιουργήσουμε όσα και αν είναι αυτά;Επίσης αυτή η αναζήτηση στο pool δεν καθυστερεί την δημιουργία των strings ειδικά αν το pool είναι μεγάλο; Γενικώς τι εξυπηρετεί; Την αποδοτικότητα από άποψη μνήμης;
defacer Δημοσ. 18 Ιουνίου 2014 Δημοσ. 18 Ιουνίου 2014 Ε θα τα διατηρήσει μέχρι ενός σημείου, όπως κι αν το έγραφες μόνος σου σε κώδικα (που είναι πολύ εύκολο). Άμα πας να βάλεις μέσα 10 τρισεκατομμύρια strings προφανώς θα κλατάρει. Η αναζήτηση στο pool είναι πάρα μα πάρα πολύ γρήγορη επειδή το pool είναι στην ουσία ένα hash table κι αυτά έχουν σε γενικές γραμμές Ο(1) αναζήτηση. Ναι, την πρώτη φορά που φορτώνεις μια νέα class στο πρόγραμμα υπάρχει ένα πολύ μικρό runtime cost λόγω του interning αλλά τα ωφέλη (μπορείς να κάνεις lightning-fast σύγκριση με == και μειώνεται η χρήση μνήμης αν έχεις πολλαπλά αντίγραφα του ίδιου string όπως είπες) είναι γενικά πολύ μεγαλύτερα. 1
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα