Programovanie

Java 101: Prehliadka základných funkcií jazyka Java, časť 5

Predchádzajúca 1 2 Strana 2 Strana 2 z 2

Zadajte odvodenie a generické konštruktory pre všeobecné a negenerické triedy

Generické a negenerické triedy môžu deklarovať generické konštruktory, v ktorých má konštruktor formálny zoznam parametrov typu. Môžete napríklad deklarovať nasledujúcu generickú triedu pomocou generického konštruktora:

 public class Box {public Box (T t) {// ...}} 

Toto vyhlásenie určuje všeobecnú triedu Krabica s parametrom formálneho typu E. Tiež určuje všeobecný konštruktor s parametrom formálneho typu T. Generickú triedu môžete vytvoriť inštanciou a vyvolať jej konštruktor nasledovne:

 nový box („Aggies“) 

Tento výraz vytvára inštanciu Krabica, absolvovanie Mramor do E. Kompilátor tiež odvodzuje String ako Tskutočný argument typu, pretože argumentom konštruktora je a String objekt.

Kompilátory pred Java 7 odvodzujú argumenty skutočného typu generického konštruktora podobne ako argumenty generickej metódy. Kompilátor Java 7 však môže odvodiť argumenty skutočného typu generickej triedy, ktorá je inštancovaná v kontexte diamantového operátora. Uvažujme o nasledujúcom príklade:

 Box box = nový Box („Aggies“); 

Rovnako ako vyvodenie typu Mramor pre parameter formálneho typu E generickej triedy Krabica, odvodzuje typ kompilátora String pre parameter formálneho typu T konštruktora tejto generickej triedy.

Malá zmena projektu Coin # 8: Zjednodušené vyvolanie metódy varargs

Pred jazykom Java 7 sa každý pokus o vyvolanie varargs (argumenty premenných, tiež známych ako variabilná aritita) metóda s typom nevarovateľných varargs spôsobila, že kompilátor vydal varovanie „nebezpečná operácia“. Aby sa eliminoval potenciál mnohých podobných varovných správ (jedna na stránku hovoru), Java 7 presunula varovanie zo stránky hovoru na deklaráciu metódy.

Obnoviteľné a nerefikovateľné typy

A opakovateľný typ vystavuje svoje úplné informácie o type za behu. Príklady zahŕňajú primitívne typy, negenerické typy, nespracované typy a vyvolanie neviazaných zástupných znakov. Naproti tomu a nereferovateľný typ má informácie o type odstránené v čase kompilácie vymazaním typu, aby bola zaistená binárna kompatibilita s knižnicami Java a aplikáciami, ktoré boli vytvorené pred generikami. Príklady zahŕňajú Nastaviť a Nastaviť. Pretože typ, ktorý sa nedá opätovne vymeniť, nie je za behu úplne k dispozícii, server JVM nedokáže rozlíšiť medzi Nastaviť a Nastaviť; za behu iba surový typ Nastaviť je k dispozícii.

Môžu spôsobiť všeobecné metódy, ktoré zahŕňajú vstupné parametre vararg halda znečistenie, v ktorom premenná parametrizovaného typu odkazuje na objekt, ktorý nie je tohto parametrizovaného typu (napríklad ak bol zmiešaný surový typ s parametrizovaným typom). Kompilátor nahlási „nezaškrtnuté varovanie“, pretože nie je možné overiť správnosť operácie týkajúcej sa parametrizovaného typu (napríklad obsadenie alebo volanie metódy).

Výpis 13 demonštruje haldy znečistenia v prostredí, ktoré nie je variabilné.

Zoznam 13. Preukazovanie znečistenia haldy v kontexte, ktorý nie je variabilný

 import java.util.Iterator; import java.util.Set; import java.util.TreeSet; public class HeapPollutionDemo {public static void main (String [] args) {Set s = new TreeSet (); Nastaviť ss = s; // nezaškrtnuté varovanie s.add (new Integer (42)); // ďalšie nezaškrtnuté varovanie Iterator iter = ss.iterator (); while (iter.hasNext ()) {String str = iter.next (); // ClassCastException vyvolaná System.out.println (str); }}} 

Variabilné ss má parametrizovaný typ Nastaviť. Keď java.util.Set na ktoré odkazuje s je priradený k ss, kompilátor vygeneruje nekontrolované varovanie. Robí to preto, lebo to kompilátor nedokáže určiť s označuje a Nastaviť typu (nie je). Výsledkom je halda znečistenia. (Kompilátor umožňuje tomuto priradeniu zachovať spätnú kompatibilitu so staršími verziami Java, ktoré nepodporujú generické typy. Ďalej, transformácie mazania typu Nastaviť do Nastaviť, ktorého výsledkom je jeden Nastaviť bol pridelený inému Nastaviť.)

Kompilátor vygeneruje druhé nezaškrtnuté varovanie na riadku, ktorý vyvolá Nastaviťje pridať () metóda. Robí to preto, lebo nedokáže určiť, či je premenná s označuje a Nastaviť alebo Nastaviť typu. Toto je ďalšia situácia so znečistením haldy. (Kompilátor umožňuje toto volanie metódy, pretože mazanie sa transformuje Nastaviťje boolovský prírastok (E e) metóda do boolean add (Objekt o), ktorý môže do sady pridať akýkoľvek druh objektu, vrátane java.lang.Integer podtyp java.lang.Objekt.)

Znečistenie haldy sa môže ľahko vyskytnúť v rôznych variantoch. Zvážte napríklad záznam č. 14.

Zoznam 14. Preukazovanie znečistenia haldy v kontexte varargs

 importovať java.util.Arrays; import java.util.List; public class UnsafeVarargsDemo {public static void main (String [] args) {unsafe (Arrays.asList ("A", "B", "C"), Arrays.asList ("D", "E", "F") ); } static void unsafe (List ... l) {Object [] oArray = l; oArray [0] = Arrays.asList (nový Double (3.5)); Reťazec s = l [0] .get (0); }} 

The Objekt [] oArray = l; zadanie predstavuje možnosť znečistenia haldy. Hodnota, ktorá sa nezhoduje s parametrizovaným typom parametra varargs l možno priradiť k premennej oArray. Kompilátor však negeneruje nezaškrtnuté varovanie, pretože tak už urobil pri preklade Zoznam ... l do Zoznam [] l. Toto priradenie je platné, pretože premenná l má typ Zoznam [], ktoré podtypy Objekt [].

Kompilátor tiež nevydá varovanie ani chybu pri priradení a Zoznam objekt ľubovoľného typu na ktorýkoľvek z oArraykomponenty poľa; napríklad, oArray [0] = Arrays.asList (nový Double (3.5));. Toto priradenie sa priradí k prvej zložke poľa v oArray a Zoznam objekt obsahujúci jednu java.lang.Double objekt.

The Reťazec s = l [0] .get (0); zadanie je problematické. Objekt uložený v prvom komponente poľa premennej l má typ Zoznam, ale toto priradenie očakáva objekt typu Zoznam. Vo výsledku vhadzuje JVM java.lang.ClassCastException.

Zostavte tento zdrojový kód (javac -Xlint: nezačiarknuté políčko UnsafeVarargsDemo.java). Pri kompilácii pod aktualizáciou Java SE 7, verzia 6, by ste mali dodržiavať nasledujúci výstup (mierne preformátovaný kvôli čitateľnosti):

 UnsafeVarargsDemo.java:8: varovanie: [nezačiarknuté] nekontrolované vytvorenie generického poľa pre parameter varargs typu List [] nebezpečné (Arrays.asList ("A", "B", "C"), ^ UnsafeVarargsDemo.java:12: varovanie : [nezačiarknuté] Možné znečistenie haldy parametrizovaným typom vararg Zoznam statických neplatných nebezpečných (Zoznam ... l) ^ 2 varovania 

V mojom úvode do generík v jazyku Java 101 som uviedol, že vo výrazoch na vytváranie polí nemôžete používať parametre typu. Napríklad nemôžete určiť prvky = nový E [veľkosť];. Keď sa o to pokúsite, kompilátor nahlási správu „chyba pri vytváraní generického poľa“. Stále je však možné vytvoriť všeobecné pole, ale iba v kontexte varargs, a to je hlásenie prvej varovnej správy. V zákulisí sa prekladač transformuje Zoznam ... l do Zoznam [] l a potom do Zoznam [] l.

Všimnite si, že varovanie pred haldou sa generuje na nebezpečný () stránka deklarácie metódy. Táto správa sa negeneruje na stránke volania tejto metódy, čo je prípad kompilátorov Java 5 a 6.

Nie všetky varargsove metódy prispejú k znečisteniu haldy. Na mieste deklarácie metódy však bude stále vydaná varovná správa. Ak viete, že vaša metóda neprispieva k znečisteniu haldy, môžete toto varovanie potlačiť vyhlásením pomocou @SafeVarargs anotácia - Java 7 predstavila java.lang.SafeVarargs typ anotácie. Napríklad preto, lebo neexistuje spôsob, ako Polia triedy asList () metóda prispievajúca k hromadeniu znečistenia, vyhlásenie tejto metódy bolo anotované @SafeVarargs, nasledovne:

 @SafeVarargs verejný statický zoznam ako zoznam (T ... a) 

The @SafeVarargs anotácia eliminuje vytváranie generických polí a varovné správy o znečistení haldy. Je to zdokumentovaná súčasť zmluvy o metóde a tvrdí, že implementácia metódy nebude nesprávne spracovávať formálny parameter varargs.

Na záver

Java 7 zlepšila produktivitu vývojárov zavedením automatickej správy zdrojov prostredníctvom príkazu try-with-resources spolu s novým Automatické uzatváranie rozhranie, switch-on-string, multi-catch, final rethrow, binárne literály, podčiarkovníky v numerických literáloch, zmeny v algoritme odvodzovania typu kompilátora, ktorý zaviedol takzvaného diamantového operátora, a zjednodušené vyvolanie varargsovej metódy. Ďalej na Java 101: Nová generácia séria predstavuje pohľad na lambda a funkčné jazykové vlastnosti rozhrania Java 8.

Tento príbeh, „Java 101: Prehliadka základných funkcií jazyka Java, časť 5“, bol pôvodne publikovaný spoločnosťou JavaWorld.

$config[zx-auto] not found$config[zx-overlay] not found