Προγραμματισμός

Μέθοδος υπερφόρτωσης στο JVM

Καλώς ήλθατε στο νέο Java Challengers ιστολόγιο! Αυτό το blog είναι αφιερωμένο σε προκλητικές έννοιες στον προγραμματισμό Java. Κατακτήστε τους και θα είστε καλά στο δρόμο σας για να γίνετε ένας εξειδικευμένος προγραμματιστής Java.

Οι τεχνικές σε αυτό το ιστολόγιο απαιτούν λίγη προσπάθεια για την εξειδίκευση, αλλά θα κάνουν μεγάλη διαφορά στην καθημερινή σας εμπειρία ως προγραμματιστής Java. Η αποφυγή σφαλμάτων είναι ευκολότερη όταν ξέρετε πώς να εφαρμόσετε σωστά τις βασικές τεχνικές προγραμματισμού Java και η παρακολούθηση σφαλμάτων είναι πολύ πιο εύκολη όταν γνωρίζετε ακριβώς τι συμβαίνει στον κώδικα Java.

Είστε έτοιμοι να ξεκινήσετε να ελέγχετε τις βασικές έννοιες στον προγραμματισμό Java; Τότε ας ξεκινήσουμε με το πρώτο Java Challenger!

Ορολογία: Μέθοδος υπερφόρτωσης

Λόγω του όρου υπερφόρτωση, οι προγραμματιστές τείνουν να πιστεύουν ότι αυτή η τεχνική θα υπερφορτώσει το σύστημα, αλλά αυτό δεν ισχύει. Στον προγραμματισμό, μέθοδος υπερφόρτωσης σημαίνει τη χρήση του ίδιου ονόματος μεθόδου με διαφορετικές παραμέτρους.

Τι είναι η μέθοδος υπερφόρτωσης;

Μέθοδος υπερφόρτωσης είναι μια τεχνική προγραμματισμού που επιτρέπει στους προγραμματιστές να χρησιμοποιούν το ίδιο όνομα μεθόδου πολλές φορές στην ίδια τάξη, αλλά με διαφορετικές παραμέτρους. Σε αυτήν την περίπτωση, λέμε ότι η μέθοδος είναι υπερφορτωμένη. Η λίστα 1 εμφανίζει μια μεμονωμένη μέθοδο της οποίας οι παράμετροι διαφέρουν ως προς τον αριθμό, τον τύπο και τη σειρά.

Λίστα 1. Τρεις τύποι υπερφόρτωσης μεθόδων

 Αριθμός παραμέτρων: Υπολογιστής δημόσιας τάξης {void calcul (int number1, int number2) {} void calcul (int number1, int number2, int number3) {}} Τύπος παραμέτρων: public class Calculator {void calcul (int number1, int number2 ) {} υπολογισμός κενού (διπλός αριθμός1, διπλός αριθμός2) {}} Σειρά παραμέτρων: υπολογιστής δημόσιας κλάσης {υπολογισμός κενού (διπλός αριθμός1, αριθμός int2) {} υπολογισμός κενού (αριθμός int1, διπλός αριθμός2) {}} 

Μέθοδος υπερφόρτωσης και πρωτόγονοι τύποι

Στην λίστα 1, βλέπετε τους πρωτόγονους τύπους int και διπλό. Θα συνεργαστούμε περισσότερο με αυτούς και άλλους τύπους, οπότε αφιερώστε ένα λεπτό για να ελέγξετε τους πρωτόγονους τύπους στην Java.

Πίνακας 1. Πρωτόγονοι τύποι σε Java

ΤύποςΕύροςΠροκαθορισμένοΜέγεθοςΠαράδειγμα κυριολεκτικών
boolean σωστό ή λάθος ψευδής 1 bit Σωστό Λάθος
ψηφιόλεξη -128 .. 127 0 8 bits 1, -90, 128
απανθρακώνω Χαρακτήρας Unicode ή 0 έως 65,536 \ u0000 16 bits "a", "\ u0031", "\ 201", "\ n", 4
μικρός -32,768 .. 32,767 0 16 bits 1, 3, 720, 22,000
int -2,147,483,648 .. 2,147,483,647 0 32 bit -2, -1, 0, 1, 9
μακρύς -9.223.372.036.854.775.808 έως 9.223.372.036.854.775.807 0 64 bits -4000L, -900L, 10L, 700L
φλοτέρ 3,40282347 x 1038, 1,40239846 x 10-45 0.0 32 bit 1.67e200f, -1.57e-207f, .9f, 10.4F
διπλό

1.7976931348623157 x 10308, 4.9406564584124654 x 10-324

 0.0 64 bits 1.e700d, -123457e, 37e1d

Γιατί να χρησιμοποιήσω τη μέθοδο υπερφόρτωσης;

Η υπερφόρτωση καθιστά τον κώδικα καθαρότερο και ευκολότερο στην ανάγνωση και μπορεί επίσης να σας βοηθήσει να αποφύγετε σφάλματα στα προγράμματά σας.

Σε αντίθεση με την καταχώριση 1, φανταστείτε ένα πρόγραμμα όπου είχατε πολλά υπολογίζω() μεθόδους με ονόματα όπως υπολογίζω1, υπολογισμός2, υπολογίστε3 . . . δεν είναι καλό, έτσι; Υπερφόρτωση του υπολογίζω() Η μέθοδος σάς επιτρέπει να χρησιμοποιείτε το ίδιο όνομα μεθόδου ενώ αλλάζετε μόνο όσα πρέπει να αλλάξετε: τις παραμέτρους. Είναι επίσης πολύ εύκολο να βρείτε μεθόδους υπερφόρτωσης, επειδή ομαδοποιούνται στον κώδικα σας.

Αυτό που δεν είναι υπερφόρτωση

Λάβετε υπόψη ότι αλλάζοντας το όνομα μιας μεταβλητής δεν είναι υπερφόρτωση. Ο ακόλουθος κωδικός δεν θα μεταγλωττιστεί:

 υπολογιστής δημόσιας τάξης {void calcul (int firstNumber, int secondNumber) {} void calcul (int secondNumber, int thirdNumber) {}} 

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

 υπολογιστής δημόσιας κλάσης {διπλός υπολογισμός (int αριθμός1, int αριθμός2) {return 0.0;} long calcul (int number1, int number2) {return 0;}} 

Υπερφόρτωση κατασκευαστή

Μπορείτε να υπερφορτώσετε έναν κατασκευαστή με τον ίδιο τρόπο που θα κάνατε μια μέθοδο:

 Υπολογιστής δημόσιας τάξης {private int number1; ιδιωτικό αριθμό int2; δημόσια αριθμομηχανή (int number1) {this.number1 = number1;} public Calculator (int number1, int number2) {this.number1 = number1; this.number2 = number2; }} 

Πάρτε τη μέθοδο πρόκλησης υπερφόρτωσης!

Είστε έτοιμοι για το πρώτο σας Java Challenger; Ας ανακαλύψουμε!

Ξεκινήστε εξετάζοντας προσεκτικά τον ακόλουθο κώδικα.

Λίστα 2. Προηγμένη πρόκληση υπερφόρτωσης μεθόδου

 δημόσια τάξη AdvancedOverloadingChallenge3 {static String x = ""; public static void main (String ... doYourBest) {executeAction (1); executeAction (1.0); executeAction (Double.valueOf ("5")); executeAction (1L); System.out.println (x); } static void executeAction (int ... var) {x + = "a"; } static void executeAction (Integer var) {x + = "b"; } static void executeAction (Object var) {x + = "c"; } static void executeAction (σύντομο var) {x + = "d"; } static void executeAction (float var) {x + = "e"; } static void executeAction (διπλό var) {x + = "f"; }} 

Εντάξει, έχετε ελέγξει τον κώδικα. Ποια είναι η έξοδος;

  1. befe
  2. bfce
  3. εφέ
  4. π.μ.

Ελέγξτε την απάντησή σας εδώ.

Τι συνέβη μόλις τώρα? Πώς η JVM συγκεντρώνει υπερφορτωμένες μεθόδους

Για να κατανοήσετε τι συνέβη στη Λίστα 2, πρέπει να γνωρίζετε ορισμένα πράγματα σχετικά με τον τρόπο με τον οποίο η JVM μεταγλωττίζει μεθόδους υπερφόρτωσης.

Πρώτα απ 'όλα, το JVM είναι έξυπνα τεμπέλης: θα καταβάλλει πάντα την ελάχιστη δυνατή προσπάθεια για την εκτέλεση μιας μεθόδου. Έτσι, όταν σκέφτεστε πώς το JVM χειρίζεται την υπερφόρτωση, λάβετε υπόψη τρεις σημαντικές τεχνικές μεταγλωττιστών:

  1. Πλάτυνση
  2. Πυγμαχία (αυτόματη αποστολή και αποσυσκευασία)
  3. Varargs

Εάν δεν έχετε συναντήσει ποτέ αυτές τις τρεις τεχνικές, μερικά παραδείγματα θα σας βοηθήσουν να τα καταστήσετε σαφή. Σημειώστε ότι η JVM τους εκτελεί με τη δοθείσα σειρά.

Εδώ είναι ένα παράδειγμα πλάτυνση:

 int primitiveIntNumber = 5; double primitiveDoubleNumber = primitiveIntNumber; 

Αυτή είναι η σειρά των πρωτόγονων τύπων όταν διευρύνεται:

Ραφαέλ ντελ Νερό

Εδώ είναι ένα παράδειγμα αυτόματη αποστολή:

 int primitiveIntNumber = 7; Integer wrapperIntegerNumber = primitiveIntNumber; 

Σημειώστε τι συμβαίνει πίσω από τα παρασκήνια κατά τη σύνταξη αυτού του κώδικα:

 Integer wrapperIntegerNumber = Integer.valueOf (primitiveIntNumber); 

Και εδώ είναι ένα παράδειγμααπεμπλοκή:

 Integer wrapperIntegerNumber = 7; int primitiveIntNumber = wrapperIntegerNumber; 

Εδώ είναι τι συμβαίνει πίσω από τα παρασκήνια κατά τη σύνταξη αυτού του κώδικα:

 int primitiveIntNumber = wrapperIntegerNumber.intValue (); 

Και εδώ είναι ένα παράδειγμα varargs; σημειώστε ότι varargs είναι πάντα η τελευταία που εκτελείται:

 εκτέλεση (αριθμοί… int) {} 

Τι είναι το Varargs;

Χρησιμοποιείται για μεταβλητά ορίσματα, varargs είναι βασικά ένας πίνακας τιμών που καθορίζονται από τρεις τελείες (…) Μπορούμε να περάσουμε όσες πολλές int αριθμούς που θέλουμε σε αυτήν τη μέθοδο.

Για παράδειγμα:

εκτέλεση (1,3,4,6,7,8,8,6,4,6,88 ...) · // Θα μπορούσαμε να συνεχίσουμε… 

Το Varargs είναι πολύ βολικό επειδή οι τιμές μπορούν να μεταφερθούν απευθείας στη μέθοδο. Εάν χρησιμοποιούσαμε πίνακες, θα έπρεπε να δημιουργήσουμε instantiate τον πίνακα με τις τιμές.

Διεύρυνση: Ένα πρακτικό παράδειγμα

Όταν περνάμε τον αριθμό 1 απευθείας στο executeAction μέθοδος, το JVM το αντιμετωπίζει αυτόματα ως int. Γι 'αυτό ο αριθμός δεν πηγαίνει στο executeAction (σύντομη μεταβλητή) μέθοδος.

Ομοίως, αν περάσουμε τον αριθμό 1.0, η JVM αναγνωρίζει αυτόματα αυτόν τον αριθμό ως α διπλό.

Φυσικά, ο αριθμός 1.0 θα μπορούσε επίσης να είναι φλοτέρ, αλλά ο τύπος είναι προκαθορισμένος. Γι 'αυτό το executeAction (διπλό var) η μέθοδος καλείται στη λίστα 2.

Όταν χρησιμοποιούμε το Διπλό τύπος περιτυλίγματος, υπάρχουν δύο δυνατότητες: είτε ο αριθμός του περιτυλίγματος θα μπορούσε να είναι αποσυμπιεσμένος σε πρωτόγονο τύπο, είτε θα μπορούσε να διευρυνθεί σε Αντικείμενο. (Να θυμάστε ότι κάθε τάξη στην Java επεκτείνει το Αντικείμενο σε αυτή την περίπτωση, η JVM επιλέγει να ξεπεράσει το Διπλό πληκτρολογήστε σε ένα Αντικείμενο γιατί χρειάζεται λιγότερη προσπάθεια από ό, τι το unboxing, όπως εξήγησα προηγουμένως.

Ο τελευταίος αριθμός που περνάμε είναι 1L και επειδή έχουμε καθορίσει τον τύπο μεταβλητής αυτή τη φορά, είναι μακρύς.

Πρόκληση βίντεο! Υπερφόρτωση μεθόδου εντοπισμού σφαλμάτων

Ο εντοπισμός σφαλμάτων είναι ένας από τους ευκολότερους τρόπους για να απορροφήσετε πλήρως τις έννοιες προγραμματισμού, βελτιώνοντας παράλληλα τον κώδικά σας. Σε αυτό το βίντεο μπορείτε να ακολουθήσετε ενώ εντοπίζω το σφάλμα και εξηγώ τη μέθοδο πρόκλησης υπερφόρτωσης:

Συνηθισμένα λάθη με υπερφόρτωση

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

Αυτόματο κιβώτιο με περιτυλίγματα

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

 int primitiveIntNumber = 7; Double wrapperNumber = primitiveIntNumber; 

Το Autoboxing θα λειτουργεί μόνο με το διπλό πληκτρολογήστε γιατί αυτό που συμβαίνει όταν συντάσσετε αυτόν τον κωδικό είναι το ίδιο με το ακόλουθο:

 Διπλός αριθμός = Double.valueOf (primitiveIntNumber); 

Ο παραπάνω κωδικός θα μεταγλωττιστεί. Ο πρώτοςint ο τύπος θα διευρυνθεί σε διπλό και στη συνέχεια θα είναι κουτί Διπλό. Αλλά όταν γίνεται αυτόματη αποστολή, δεν υπάρχει τύπος διεύρυνσης και ο κατασκευαστής από Double.valueOf θα λάβει ένα διπλό, όχι ένα int. Σε αυτήν την περίπτωση, το autoboxing θα λειτουργούσε μόνο αν εφαρμόζαμε cast, όπως έτσι:

 Double wrapperNumber = (double) primitiveIntNumber; 

Να θυμάστε ότιΑκέραιος αριθμός δεν μπορεί Μακρύς και Φλοτέρ δεν μπορεί Διπλό. Δεν υπάρχει κληρονομιά. Κάθε ένας από αυτούς τους τύπους--Ακέραιος αριθμός, Μακρύς, Φλοτέρ, και Διπλό - είναιένα Αριθμός και ένα Αντικείμενο.

Σε περίπτωση αμφιβολίας, απλώς θυμηθείτε ότι οι αριθμοί περιτυλίγματος μπορούν να διευρυνθούν Αριθμός ή Αντικείμενο. (Υπάρχουν πολλά περισσότερα για να εξερευνήσουμε τα περιτυλίγματα, αλλά θα το αφήσω για μια άλλη ανάρτηση.)

Τύποι κωδικοποιημένων αριθμών στο JVM

Όταν δεν καθορίζουμε έναν τύπο σε έναν αριθμό, το JVM θα το κάνει για εμάς. Εάν χρησιμοποιήσουμε τον αριθμό 1 απευθείας στον κώδικα, το JVM θα το δημιουργήσει ως int. Εάν προσπαθήσετε να περάσετε το 1 απευθείας σε μια μέθοδο που λαμβάνει ένα μικρός, δεν θα μεταγλωττιστεί.

Για παράδειγμα:

 class Calculator {public static void main (String… args) {// Αυτή η επίκληση μεθόδου δεν θα μεταγλωττιστεί // Ναι, 1 θα μπορούσε να είναι char, short, byte, αλλά το JVM το δημιουργεί ως int υπολογισμός (1). } άκυρος υπολογισμός (σύντομος αριθμός) {}} 

Ο ίδιος κανόνας θα εφαρμοστεί όταν χρησιμοποιείτε τον αριθμό 1.0. αν και θα μπορούσε να είναι φλοτέρ, η JVM θα αντιμετωπίζει αυτόν τον αριθμό ως διπλό:

 class Calculator {public static void main (String… args) {// Αυτή η επίκληση μεθόδου δεν θα μεταγλωττιστεί // Ναι, 1 θα μπορούσε να είναι float, αλλά το JVM το δημιουργεί ως διπλός υπολογισμός (1.0). } άκυρος υπολογισμός (αριθμός float) {}} 

Ένα άλλο κοινό λάθος είναι να πιστεύουμε ότι το Διπλό ή οποιοσδήποτε άλλος τύπος περιτυλίγματος θα ταιριάζει καλύτερα στη μέθοδο που λαμβάνει ένα διπλό. Στην πραγματικότητα, χρειάζεται λιγότερη προσπάθεια για την JVM ευρύνω ο Διπλό περιτύλιγμα σε ένα Αντικείμενο αντί να το αποσυνδέσετε σε ένα διπλό πρωτόγονος τύπος.

Συνοψίζοντας, όταν χρησιμοποιείται απευθείας σε κώδικα Java, 1 θα είναι int και το 1.0 θα είναι διπλό. Η επέκταση είναι η πιο αργή διαδρομή προς εκτέλεση, το επόμενο εγκιβωτισμό ή το unboxing έρχεται στη συνέχεια, και η τελευταία λειτουργία θα είναι πάντα varargs.

Ως περίεργο γεγονός, ξέρατε ότι το απανθρακώνω ο τύπος δέχεται αριθμούς;

 char anyChar = 127; // Ναι, αυτό είναι παράξενο, αλλά καταρτίζει 

Τι πρέπει να θυμάστε για την υπερφόρτωση

Η υπερφόρτωση είναι μια πολύ ισχυρή τεχνική για σενάρια όπου χρειάζεστε το ίδιο όνομα μεθόδου με διαφορετικές παραμέτρους. Είναι μια χρήσιμη τεχνική, επειδή το σωστό όνομα στον κώδικά σας δημιουργεί μεγάλο διαφορά για αναγνωσιμότητα. Αντί να αντιγράψετε τη μέθοδο και να προσθέσετε ακαταστασία στον κώδικά σας, μπορείτε απλά να την υπερφορτώσετε. Με αυτόν τον τρόπο, ο κώδικάς σας θα είναι καθαρός και ευανάγνωστος και μειώνεται ο κίνδυνος οι διπλές μέθοδοι να σπάσουν κάποιο μέρος του συστήματος.

Τι πρέπει να θυμάστε: Όταν υπερφορτώνετε μια μέθοδο, το JVM θα καταστήσει την ελάχιστη δυνατή προσπάθεια. αυτή είναι η σειρά της πιο αργής διαδρομής προς εκτέλεση:

  • Πρώτα διευρύνεται
  • Δεύτερον είναι η πυγμαχία
  • Το τρίτο είναι το Varargs

Τι να προσέξετε: Οι δύσκολες καταστάσεις θα προκύψουν από την άμεση δήλωση ενός αριθμού: 1 θα είναι int και το 1.0 θα είναι διπλό.

Επίσης, θυμηθείτε ότι μπορείτε να δηλώσετε αυτούς τους τύπους ρητά χρησιμοποιώντας τη σύνταξη 1F ή 1f για a φλοτέρ ή 1D ή 1d για a διπλό.

Αυτό ολοκληρώνει το πρώτο μας Java Challenger, παρουσιάζοντας τον ρόλο του JVM στη μέθοδο υπερφόρτωσης. Είναι σημαντικό να συνειδητοποιήσουμε ότι το JVM είναι εγγενώς τεμπέλης και θα ακολουθεί πάντα τον πιο χαλαρό δρόμο προς εκτέλεση.

 

Κλειδί απάντησης

Η απάντηση στο Java Challenger στη λίστα 2 είναι: Επιλογή 3. efce.

Περισσότερα σχετικά με τη μέθοδο υπερφόρτωσης στην Java

  • Java 101: Μαθήματα και αντικείμενα στην Java: Μια πραγματική εισαγωγή για αρχάριους σε τάξεις και αντικείμενα, συμπεριλαμβανομένων σύντομων ενοτήτων για μεθόδους και μεθόδους υπερφόρτωσης.
  • Java 101: Στοιχεία στοιχειώδους γλώσσας Java: Μάθετε περισσότερα για το γιατί έχει σημασία ότι η Java είναι μια έντονα δακτυλογραφημένη γλώσσα και λάβετε μια πλήρη εισαγωγή στους πρωτόγονους τύπους στην Java.
  • Πάρα πολλές παράμετροι στις μεθόδους Java, Μέρος 4: Εξερευνήστε τους περιορισμούς και τα μειονεκτήματα της υπερφόρτωσης μεθόδων και πώς μπορούν να αντιμετωπιστούν ενσωματώνοντας προσαρμοσμένους τύπους και αντικείμενα παραμέτρων.

Αυτή η ιστορία, "Μέθοδος υπερφόρτωσης στο JVM" δημοσιεύθηκε αρχικά από την JavaWorld.