java:generics_raw

Απλοί παραμετρικοί τύποι δεδομένων (Raw Generic Types)

Όπως δείξαμε προηγούμενα, τα αντικείμενα της κλάσης Box ορίζονται σε συνδυασμό με ένα reference τύπο δεδομένων. Υπάρχει η δυνατότητα να ορίσετε ένα αντικείμενο της κλάσης Box χωρίς την χρήση της επιπλέον παραμέτρου, όπως παρακάτω.

Box b = new Box();

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

Box<Object> b = new Box<Object>();

Η προσπάθεια μεταγλώττισης του παρακάτω κώδικα καταδεικνύει το παραπάνω

BoxUsage.java
public class BoxUsage {
   public static void main(String args[]) {
     Box b = new Box(5);
     Box<Number> bn = new Box<>();
     bn.set(b.get());     
   }
}

Το μήνυμα που εμφανίζει ο μεταγλωττιστής για τον παραπάνω κώδικα είναι το εξής:

$> javac BoxUsage.java 
BoxUsage.java:5: error: method set in class Box<T> cannot be applied to given types;
     bn.set(b.get());     
       ^
  required: Number
  found: Object
  reason: actual argument Object cannot be converted to Number by method invocation conversion
  where T is a type-variable:
    T extends Object declared in class Box
Note: BoxUsage.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error

Αν αλλάξετε την γραμμή Box<Number> bn = new Box<>(); σε Box<Object> bn = new Box<>(); το λάθος μεταγλώττισης εξαφανίζεται και εμφανίζεται ένα warning που επισημαίνει ότι στην γραμμή 3 χρησιμοποιείται ένας παραμετρικός τύπος ως απλός (raw generic type).

ΔΕΝ συνιστάται σε καμία περίπτωση η χρήση παραμετρικών τύπων (generic types) ως απλών.

Compiler warnings από τη μίξη παραμετρικών και μη παραμετρικών τύπων δεδομένων

Η μη χρήση των παραμετρικών τύπων δεδομένων δυσκολεύει τον μεταγλωττιστή να αποφασίσει για την ασφαλή ή μη ασφαλή χρήση των δεδομένων που θα αποθηκευτούν στην κλάση. Η μίξη generics με raw types μπορεί να δημιουργήσει warnings της παρακάτω μορφής κατά την μεταγλώττιση.

Note: Example.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

Δείτε τα παρακάτω παραδείγματα κώδικα

Box<String> stringBox = new Box<>();
Box rawBox = stringBox;           // Safe - OK
Box rawBox = new Box();           // rawBox is a raw type of Box<T>
Box<Integer> intBox = rawBox;     // warning: unchecked conversion
Box<String> stringBox = new Box<>();
Box rawBox = stringBox;
rawBox.set(8);                    // warning: unchecked invocation to set(T)

Το παρακάτω παράδειγμα είναι επίσης ενδεικτικό:

WarningDemo.java
public class WarningDemo {
    public static void main(String[] args){
        Box<Integer> bi;
        bi = createBox();
    }
 
    static Box createBox(){
        return new Box();
    }
}

Μεταγλωττίζοντας με το flag -Xlint:unchecked εμφανίζεται το παρακάτω μήνυμα.

WarningDemo.java:4: warning: [unchecked] unchecked conversion
found   : Box
required: Box<java.lang.Integer>
        bi = createBox();
                      ^
1 warning
java/generics_raw.txt · Last modified: 2017/05/05 06:22 by gthanos