Programování

Java 101: Prohlídka základních funkcí jazyka Java, část 5

Předchozí 1 2 Strana 2 Stránka 2 ze 2

Zadejte odvození a generické konstruktory pro obecné a negenerické třídy

Obecné a negenerické třídy mohou deklarovat obecné konstruktory, ve kterých má konstruktor formální seznam parametrů typu. Můžete například deklarovat následující obecnou třídu pomocí generického konstruktoru:

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

Toto prohlášení určuje obecnou třídu Krabice s parametrem formálního typu E. Určuje také obecný konstruktor s parametrem formálního typu T. Generickou třídu můžete vytvořit instanci a vyvolat její konstruktor následujícím způsobem:

 nový rámeček („Aggies“) 

Tento výraz vytvoří instanci Krabiceprojíždějící Mramor na E. Kompilátor také odvozuje Tětiva tak jako TSkutečný argument typu, protože argument konstruktoru je a Tětiva objekt.

Kompilátory z Pre-Java 7 odvozují argumenty skutečného typu generického konstruktoru podobně jako argumenty generické metody. Kompilátor prostředí Java 7 však může odvodit argumenty skutečného typu generické třídy, která je vytvořena v kontextu operátoru diamantu. Zvažte následující příklad:

 Box box = nový Box ("Aggies"); 

Stejně jako odvození typu Mramor pro parametr formálního typu E generické třídy Krabice, odvozuje typ kompilátoru Tětiva pro parametr formálního typu T konstruktoru této generické třídy.

Malá změna projektu Coin # 8: Zjednodušené vyvolání metody varargs

Před Javou 7 se každý pokus vyvolat varargs (proměnné argumenty, známé také jako variabilní arity) metoda s nerefikovatelným typem varargs způsobila, že kompilátor vydal varování „nebezpečná operace“. Aby se eliminoval potenciál mnoha podobných varovných zpráv (jedna na web volání), Java 7 přesunula varování z webu volání do deklarace metody.

Reifiable a non-reifiable typy

A opakovatelný typ vystavuje své úplné informace o typu za běhu. Mezi příklady patří primitivní typy, negenerické typy, nezpracované typy a vyvolání nevázaných zástupných znaků. Naproti tomu a nenahraditelný typ má informace o typu odstraněny v době kompilace vymazáním typu, aby byla zajištěna binární kompatibilita s knihovnami Java a aplikacemi, které byly vytvořeny před generikami. Mezi příklady patří Soubor a Soubor. Protože typ, který nelze znovu identifikovat, není za běhu zcela k dispozici, nemůže JVM rozlišit rozdíl mezi Soubor a Soubor; za běhu pouze surový typ Soubor je k dispozici.

Mohou způsobit obecné metody, které zahrnují vstupní parametry vararg haldy znečištění, ve kterém proměnná parametrizovaného typu odkazuje na objekt, který není tohoto parametrizovaného typu (například pokud byl smíchán surový typ s parametrizovaným typem). Kompilátor hlásí „nezaškrtnuté varování“, protože správnost operace zahrnující parametrizovaný typ (jako přetypování nebo volání metody) nelze ověřit.

Výpis 13 demonstruje znečištění haldy v kontextu bez variací.

Výpis 13. Demonstrace znečištění haldy v kontextu bez variací

 import java.util.Iterator; import java.util.Set; import java.util.TreeSet; veřejná třída HeapPollutionDemo {public static void main (String [] args) {Set s = new TreeSet (); Nastavit ss = s; // nezaškrtnuté varování s.add (new Integer (42)); // další nezaškrtnuté varování Iterator iter = ss.iterator (); while (iter.hasNext ()) {String str = iter.next (); // ClassCastException vyvolána System.out.println (str); }}} 

Variabilní ss má parametrizovaný typ Soubor. Když sada java.util na které odkazuje s je přiřazen ss, kompilátor generuje nezaškrtnuté varování. Činí tak proto, že to překladač nemůže určit s označuje a Soubor typ (není). Výsledkem je znečištění haldy. (Kompilátor umožňuje tomuto přiřazení zachovat zpětnou kompatibilitu se staršími verzemi prostředí Java, které nepodporují generika. Dále transformace mazání typu Soubor do Soubor, jehož výsledkem je jeden Soubor byl přidělen jinému Soubor.)

Kompilátor generuje druhé nezaškrtnuté varování na řádku, který vyvolá Souborje přidat() metoda. Činí tak proto, že nemůže určit, zda je proměnná s označuje a Soubor nebo Soubor typ. Toto je další situace znečištění haldy. (Kompilátor umožňuje toto volání metody, protože mazání se transformuje Souborje boolean add (E e) metoda k boolean add (Objekt o), který může do sady přidat jakýkoli druh objektu, včetně java.lang.Integer podtyp java.lang.Object.)

Znečištění haldy může snadno nastat v kontextu varargs. Zvažte například výpis 14.

Výpis 14. Demonstrace znečištění haldy v kontextu varargs

 import 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)); Řetězec s = l [0] .get (0); }} 

The Objekt [] oArray = l; zadání zavádí možnost znečištění haldy. Hodnota neodpovídající parametrizovanému typu parametru varargs l lze přiřadit k proměnné oArray. Kompilátor však nevygeneruje nezaškrtnuté varování, protože tak již učinil při překladu Seznam ... l na Seznam [] l. Toto přiřazení je platné, protože proměnná l má typ Seznam[], které podtypy Objekt[].

Kompilátor také nevydává varování nebo chybu při přiřazování a Seznam objekt libovolného typu na některý z oArraykomponenty pole; například, oArray [0] = Arrays.asList (nový Double (3.5));. Toto přiřazení se přiřadí první komponentě pole oArray A Seznam objekt obsahující jediný java.lang.Double objekt.

The Řetězec s = l [0] .get (0); přiřazení je problematické. Objekt uložený v první komponentě pole proměnné l má typ Seznam, ale toto přiřazení očekává objekt typu Seznam. Výsledkem je, že JVM hodí java.lang.ClassCastException.

Zkompilovat tento zdrojový kód (javac -Xlint: nezaškrtnuto UnsafeVarargsDemo.java). Při kompilaci pod aktualizací Java SE 7 aktualizace 6 byste měli dodržovat následující výstup (mírně přeformátovaný kvůli čitelnosti):

 UnsafeVarargsDemo.java:8: varování: [nezaškrtnuto] nekontrolované vytvoření obecného pole pro parametr varargs typu List [] nebezpečné (Arrays.asList ("A", "B", "C"), ^ UnsafeVarargsDemo.java:12: varování : [nezaškrtnuto] Možné znečištění haldy parametrizovaným typem vararg Seznam statických neplatných nebezpečných (Seznam ... l) ^ 2 varování 

V mém úvodu k generikům Java 101 jsem uvedl, že ve výrazech pro vytváření matic nemůžete použít parametry typu. Například nemůžete určit elements = new E [size];. Když se o to pokusíte, kompilátor ohlásí zprávu „chyba při vytváření obecného pole“. Stále je však možné vytvořit obecné pole, ale pouze v kontextu varargs, a to hlásí první varovná zpráva. V zákulisí se kompilátor transformuje Seznam ... l na Seznam [] l a pak do Seznam [] l.

Všimněte si, že varování před hromadou znečištění je generováno na nebezpečný() stránka deklarace metody. Tato zpráva není generována na stránce volání této metody, což je případ kompilátorů Java 5 a 6.

Ne všechny metody Varargs přispějí ke znečištění haldy. Na místě deklarace metody však bude stále vydána varovná zpráva. Pokud víte, že vaše metoda nepřispívá ke znečištění haldy, můžete toto varování potlačit deklarací pomocí @SafeVarargs anotace - Java 7 představila java.lang.SafeVarargs typ poznámky. Například proto, že neexistuje způsob, jak Pole třídy asList () metoda, která přispívá ke znečištění haldy, byla tato deklarace této metody anotována @SafeVarargs, jak následuje:

 @SafeVarargs public static List asList (T ... a) 

The @SafeVarargs anotace eliminuje generické vytváření pole a varovné zprávy o znečištění haldy. Je to zdokumentovaná část kontraktu metody a tvrdí, že implementace metody nebude nesprávně zpracovávat formální parametr varargs.

Závěrem

Java 7 zlepšila produktivitu vývojářů zavedením automatické správy zdrojů prostřednictvím příkazu try-with-resources společně s novým Automaticky uzavíratelné interface, switch-on-string, multi-catch, final rethrow, binární literály, podtržítka v numerických literálech, změny algoritmu odvození typu kompilátoru, který zavedl takzvaný diamantový operátor, a zjednodušené vyvolání metody varargs. Další v Java 101: Nová generace série je pohled na lambda a funkční jazykové funkce rozhraní Java 8.

Tento příběh, „Java 101: Prohlídka základních funkcí jazyka Java, část 5“, původně publikoval JavaWorld.