JavaRush /Java Blog /Random-IT /Avvolgimento, scarto e imballaggio

Avvolgimento, scarto e imballaggio

Pubblicato nel gruppo Random-IT
Ciao! Hai già abbastanza familiarità con i tipi primitivi e hai lavorato molto con loro. Avvolgimento, scarto e imballaggio - 1Le primitive nella programmazione, e in Java in particolare, presentano molti vantaggi: occupano poca memoria, aumentando così l'efficienza del programma, e sono chiaramente suddivise in intervalli di valori. Tuttavia, nel processo di apprendimento di Java, abbiamo ripetuto più di una volta, come un mantra, “ in Java tutto è un oggetto ”. Ma i primitivi sono una confutazione diretta di queste parole. Non sono oggetti. Quindi il principio “tutto è oggetto” è falso? Non proprio. In Java ogni tipo primitivo ha il suo fratello gemello, la classe wrapper ( Wrapper). Cos'è un involucro? Un wrapper è una classe speciale che memorizza al suo interno il valore di una primitiva. Ma poiché questa è una classe, può creare le proprie istanze. Memorizzeranno i valori primitivi necessari all'interno, pur essendo oggetti reali. I nomi delle classi wrapper sono molto simili ai nomi delle corrispondenti primitive, o coincidono completamente con essi. Pertanto, sarà molto facile ricordarli.
Classi wrapper per tipi di dati primitivi
Tipi di dati primitivi Classi wrapper
int Numero intero
corto Corto
lungo Lungo
byte Byte
galleggiante Galleggiante
Doppio Doppio
car Carattere
booleano Booleano
Gli oggetti della classe wrapper vengono creati proprio come qualsiasi altro:
public static void main(String[] args) {

   Integer i = new Integer(682);

   Double d = new Double(2.33);

   Boolean b = new Boolean(false);
}
Le classi wrapper consentono di mitigare gli svantaggi dei tipi primitivi. La più ovvia è che le primitive non hanno metodi . Ad esempio, non hanno un metodo toString(), quindi non puoi, ad esempio, convertire un numero intin una stringa. Ma con una classe wrapper Integerè facile.
public static void main(String[] args) {

   Integer i = new Integer(432);

   String s = i.toString();
}
Ci saranno anche difficoltà con la trasformazione inversa. Diciamo di avere una stringa che sappiamo per certo contiene un numero. Tuttavia, nel caso di un tipo primitivo, intnon saremo in grado di ottenere questo numero dalla stringa e trasformarlo, di fatto, in un numero. Ma grazie alle classi wrapper, ora abbiamo questa opportunità.
public static void main(String[] args) {

   String s = "1166628";

   Integer i = Integer.parseInt(s);

   System.out.println(i);
}
Output: 1166628 Abbiamo recuperato con successo un numero da una stringa e assegnato a una variabile di riferimento Integer i. A proposito, sui collegamenti. Sai già che i parametri vengono passati ai metodi in modi diversi: le primitive vengono passate per valore e gli oggetti vengono passati per riferimento. Puoi utilizzare questa conoscenza durante la creazione dei tuoi metodi: se il tuo metodo funziona, ad esempio, con numeri frazionari, ma hai bisogno della logica del passaggio per riferimento, puoi passare parametri al metodo Double/Floatinvece di double/float. Inoltre, oltre ai metodi, le classi wrapper dispongono di campi statici molto comodi da utilizzare. Ad esempio, immagina di trovarti ora di fronte a un compito: stampare il numero massimo possibile sulla console int, quindi il numero minimo possibile. Il compito sembra elementare, ma difficilmente riuscirai a farlo senza Google. E le classi wrapper ti consentono facilmente di risolvere i seguenti "problemi quotidiani":
public class Main {
   public static void main(String[] args) {

       System.out.println(Integer.MAX_VALUE);
       System.out.println(Integer.MIN_VALUE);
   }
}
Tali campi ti consentono di non essere distratto da compiti più seri. Per non parlare del fatto che nel processo di stampa del numero 2147483647 (questo è esattamente MAX_VALUE) non è sorprendente digitarlo in modo errato :) Inoltre, in una delle lezioni precedenti abbiamo già attirato l'attenzione sul fatto che gli oggetti delle classi wrapper sono immutabili .
public static void main(String[] args) {

   Integer a = new Integer(0);
   Integer b = new Integer(0);

   b = a;
   a = 1;
   System.out.println(b);
}
Output: 0 L'oggetto a cui puntava originariamente il riferimento аnon ha cambiato il suo stato, altrimenti anche il valore bsarebbe cambiato. Come con String, invece di modificare lo stato dell'oggetto wrapper, viene creato in memoria un oggetto completamente nuovo. Perché i creatori di Java alla fine decisero di mantenere i tipi primitivi nel linguaggio? Dato che tutto dovrebbe essere un oggetto e disponiamo già di classi wrapper che possono essere utilizzate per esprimere tutto ciò che esprimono le primitive, perché non lasciarle semplicemente nel linguaggio e rimuovere le primitive? La risposta è semplice: prestazioni. I tipi primitivi sono chiamati primitivi perché sono privi di molte caratteristiche “pesanti” degli oggetti. Sì, un oggetto ha molti metodi convenienti, ma non sempre ne hai bisogno. A volte hai solo bisogno del numero 33, o 2.62, o del valore di true/ false. Nelle situazioni in cui tutti i vantaggi degli oggetti sono irrilevanti e non necessari al funzionamento del programma, le primitive faranno un lavoro molto migliore.

Imballaggio/disimballaggio automatico

Una delle caratteristiche delle primitive e delle loro classi wrapper in Java è l'autoboxing/autounboxing. Avvolgimento, scarto e imballaggio - 2 Cerchiamo di comprendere questo concetto. Come tu ed io abbiamo già imparato in precedenza, Java è un linguaggio orientato agli oggetti. Ciò significa che tutti i programmi scritti in Java sono costituiti da oggetti. I primitivi non sono oggetti. Tuttavia, alla variabile della classe wrapper può essere assegnato un valore di tipo primitivo. Questo processo è chiamato autoboxing . Allo stesso modo, ad una variabile di tipo primitivo può essere assegnato un oggetto di una classe wrapper. Questo processo è chiamato autounboxing . Per esempio:
public class Main {
   public static void main(String[] args) {
       int x = 7;
       Integer y = 111;
       x = y; // auto unpacking
       y = x * 123; // autopacking
   }
}
Alla riga 5 assegniamo alla primitiva x il valore di y, che è un oggetto della classe wrapper Integer. Come puoi vedere, non sono necessarie azioni aggiuntive per questo: il compilatore lo sa inte Integer, in effetti, è la stessa cosa . Questo è il disimballaggio automatico. La stessa cosa accade con l'autoboxing alla riga 6: all'oggetto y viene facilmente assegnato il valore delle primitive (x*123). Questo è un esempio di confezionamento automatico. Ecco perché viene aggiunta la parola “auto”: per assegnare riferimenti primitivi agli oggetti delle rispettive classi wrapper (e viceversa) non è necessario fare nulla, tutto avviene automaticamente . Comodo, vero? :) Un'altra grande comodità dell'auto-packing/auto-unpacking si manifesta nel funzionamento dei metodi. Il fatto è che anche i parametri del metodo sono soggetti all'autopacking e all'autounpacking . E, per esempio, se uno di loro prende due oggetti come input Integer, possiamo facilmente passare lì le primitive ordinarie int!
public class Main {
   public static void main(String[] args) {

       printNumber(7);//regular int, even without a variable
   }

   public static void printNumber(Integer i) {
       System.out.println("You entered a number" + i);
   }
}
Risultato: hai inserito il numero 7. Funziona al contrario:
public class Main {
   public static void main(String[] args) {

       printNumber(new Integer(632));
   }

   public static void printNumber(int i) {
       System.out.println("You entered a number" + i);
   }
}
Un punto importante da ricordare: l'autoboxing e l'unboxing non funzionano per gli array !
public class Main {
   public static void main(String[] args) {

       int[] i = {1,2,3,4,5};

       printArray(i);//error, won't compile!
   }

   public static void printArray(Integer[] arr) {
       System.out.println(Arrays.toString(arr));
   }
}
Tentare di passare un array di primitive a un metodo che accetta un array di oggetti come input causerà un errore di compilazione. Infine, confrontiamo ancora una volta brevemente primitive e wrapper Primitive:
  • avere un vantaggio in termini di prestazioni
Involucri:
  • Permettono di non violare il principio “tutto è un oggetto”, in modo che numeri, simboli e valori booleani vero/falso non escano da questo concetto
  • Espandi la capacità di lavorare con questi valori fornendo metodi e campi convenienti
  • Necessario quando alcuni metodi possono funzionare esclusivamente con oggetti
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION