JavaRush /Blog Jawa /Random-JV /Nggunakake varargs nalika nggarap generik

Nggunakake varargs nalika nggarap generik

Diterbitake ing grup
Hello! Ing wulangan dina iki kita bakal terus sinau babagan generik. Mesthi wae iki minangka topik gedhe, nanging ora ana sing bisa dituju - iki minangka bagean basa sing penting banget :) Nalika sampeyan sinau dokumentasi Oracle babagan generik utawa maca pandhuan ing Internet, sampeyan bakal nemokake syarat kasebut. Jinis Non-Reifiable lan Jinis Reifiable . Apa jenis tembung "Reifiable"? Malah yen kabeh iku apik karo Inggris, sampeyan ora kamungkinan kanggo ketemu. Ayo coba nerjemahake! Nggunakake varargs nalika nggarap generik - 2
*matur nuwun Google, sampeyan wis nulungi banget -_-*
Tipe reifiable yaiku jinis sing informasine kasedhiya nalika runtime. Ing basa Jawa, iki kalebu jinis primitif, jinis mentah, lan jinis non-generik. Ing kontras, Non-Reifiable Types minangka jinis sing informasi dibusak lan ora kasedhiya nalika runtime. Iki mung generik - List<String> , List<Integer> , etc.

Ngomong-ngomong, sampeyan kelingan apa varargs ?

Yen sampeyan lali, iki minangka argumen dawa variabel. Padha migunani ing kahanan sing kita ora ngerti persis carane akeh argumen sing bisa diterusake menyang metode kita. Contone, yen kita duwe kelas kalkulator lan duwe metode sum. sum()Sampeyan bisa ngliwati 2 nomer, 3, 5, utawa akeh sing sampeyan seneng karo metode kasebut . Iku bakal banget aneh kanggo kakehan cara saben wektu sum()kanggo njupuk menyang akun kabeh opsi bisa. Nanging kita bisa nindakake iki:
public class SimpleCalculator {

   public static int sum(int...numbers) {

       int result = 0;

       for(int i : numbers) {

           result += i;
       }

       return result;
   }

   public static void main(String[] args) {

       System.out.println(sum(1,2,3,4,5));
       System.out.println(sum(2,9));
   }
}
Output konsol:

15
11
Dadi, nalika digunakake varargsing kombinasi karo generik ana sawetara fitur penting. Ayo ndeleng kode iki:
import javafx.util.Pair;
import java.util.ArrayList;
import java.util.List;

public class Main {

   public static <E> void addAll(List<E> list, E... array) {

       for (E element : array) {
           list.add(element);
       }
   }

   public static void main(String[] args) {
       addAll(new ArrayList<String>(),  //  здесь все нормально
               "Leonardo da Vinci",
               "Vasco de Gama"
       );

       // а здесь мы получаем предупреждение
       addAll(new ArrayList<Pair<String, String>>(),
               new Pair<String, String>("Leonardo", "da Vinci"),
               new Pair<String, String>("Vasco", "de Gama")
       );
   }
}
Cara kasebut njupuk dhaptar lan sawetara obyek addAll()minangka input , banjur nambahake kabeh obyek kasebut menyang dhaptar. Ing metode kita nelpon metode kita kaping pindho . Pisanan kita nambah ing rong baris biasa. Kabeh apik ing kene. Kapindho kita nambah ing rong obyek . Lan ing kene kita tiba-tiba entuk peringatan: List<E>Emain()addAll()ListListPair<String, String>

Unchecked generics array creation for varargs parameter
Iki artine apa? Napa kita nampa bebaya lan apa hubungane array? Array- iki array, lan ora ana array ing kode kita! Ayo miwiti karo sing kapindho. Peringatan kasebut nyebutake array amarga compiler ngowahi argumen dawa variabel (varargs) dadi array. Ing tembung liyane, tandha cara kita yaiku addAll():
public static <E> void addAll(List<E> list, E... array)
Bener katon kaya iki:
public static <E> void addAll(List<E> list, E[] array)
Yaiku, ing metode main(), kompiler bakal ngowahi kode kita dadi:
public static void main(String[] args) {
   addAll(new ArrayList<String>(),
      new String[] {
        "Leonardo da Vinci",
        "Vasco de Gama"
      }
   );
   addAll(new ArrayList<Pair<String,String>>(),
        new Pair<String,String>[] {
            new Pair<String,String>("Leonardo","da Vinci"),
            new Pair<String,String>("Vasco","de Gama")
        }
   );
}
Kabeh apik karo array String. Nanging karo larik Pair<String, String>- ora. Kasunyatane Pair<String, String>iki minangka Tipe Non-Reifiable. Sajrone kompilasi, kabeh informasi babagan jinis parameter (<String, String>) bakal dibusak. Nggawe array saka Non-Reifiable Type ora diijini ing Jawa . Sampeyan bisa verifikasi manawa sampeyan nyoba nggawe pasangan array<String, String> kanthi manual
public static void main(String[] args) {

   //  ошибка компиляции! Generic array creation
  Pair<String, String>[] array = new Pair<String, String>[10];
}
Alesan sing jelas - jinis safety. Nalika sampeyan ngelingi, nalika nggawe array, sampeyan kudu nunjukake obyek (utawa primitif) sing bakal disimpen.
int array[] = new int[10];
Ing salah sawijining pelajaran sadurunge, kita nliti kanthi rinci babagan mekanisme mbusak jinis. Dadi, ing kasus iki, minangka asil mbusak jinis, kita ilang informasi sing Pairpasangan disimpen ing obyek kita <String, String>. Nggawe larik bakal ora aman. Nalika nggunakake metode karo varargslan generik, manawa kanggo ngelingi bab jinis erasure lan persis cara kerjane. Yen sampeyan pancen yakin karo kode sing wis ditulis, lan sampeyan ngerti manawa ora bakal nyebabake masalah, sampeyan bisa mateni varargsbebaya sing ana gandhengane nggunakake anotasi.@SafeVarargs
@SafeVarargs
public static <E> void addAll(List<E> list, E... array) {

   for (E element : array) {
       list.add(element);
   }
}
Yen sampeyan nambahake anotasi iki menyang metode sampeyan, bebaya sing ditemokake sadurunge ora bakal katon. Masalah liyane sing bisa ditindakake nalika nggunakake varargsobat umum yaiku polusi tumpukan. Nggunakake varargs nalika nggarap generik - 4Kontaminasi bisa kedadeyan ing kahanan ing ngisor iki:
import java.util.ArrayList;
import java.util.List;

public class Main {

   static List<String> makeHeapPollution() {
       List numbers = new ArrayList<Number>();
       numbers.add(1);
       List<String> strings = numbers;
       strings.add("");
       return strings;
   }

   public static void main(String[] args) {

       List<String> stringsWithHeapPollution = makeHeapPollution();

       System.out.println(stringsWithHeapPollution.get(0));
   }
}
Output konsol:

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
Ing istilah sing prasaja, polusi tumpukan minangka kahanan ing ngendi obyek saka jinis 1 kudu ana ing tumpukan А, nanging obyek saka jinis bakal ana B, amarga kesalahan safety jinis. Ing conto kita, iki kedadeyan. Kaping pisanan, kita nggawe variabel Raw numberslan menehi koleksi umum ArrayList<Number>. Sawisé iku kita nambah nomer ana 1.
List<String> strings = numbers;
Ing baris iki, kompiler nyoba ngelingake kita babagan kemungkinan kesalahan kanthi menehi peringatan " Tugas sing ora dicenthang ... ", nanging ora digatekake. Akibaté, kita duwe jinis variabel umum List<String>, sing nuduhake koleksi jinis umum ArrayList<Number>. Kahanan iki jelas bisa nyebabake alangan! Iki kedadeyan. Nggunakake variabel anyar kita, kita nambah string menyang koleksi. Tumpukan kasebut najis - kita nambahake nomer dhisik banjur senar menyang koleksi sing diketik. Compiler dielingake kita, nanging kita digatèkaké warning sawijining, nampa asil ClassCastExceptionmung nalika program lagi mlaku. Apa hubungane karo iku varargs? Gunakake varargskaro generik bisa gampang nyebabake polusi tumpukan. Punika conto prasaja:
import java.util.Arrays;
import java.util.List;

public class Main {

   static void makeHeapPollution(List<String>... stringsLists) {
       Object[] array = stringsLists;
       List<Integer> numbersList = Arrays.asList(66,22,44,12);

       array[0] = numbersList;
       String str = stringsLists[0].get(0);
   }

   public static void main(String[] args) {

       List<String> cars1 = Arrays.asList("Ford", "Fiat", "Kia");
       List<String> cars2 = Arrays.asList("Ferrari", "Bugatti", "Zaporozhets");

       makeHeapPollution(cars1, cars2);
   }
}
Apa sing kedadeyan ing kene? Amarga jinis erasure, lembar parameter kita (bakal diarani "lembar" tinimbang "dhaptar" kanggo penak) yaiku -
List<String>...stringsLists
- bakal dadi array saka sheets - List[]karo jinis dingerteni (aja lali sing varargs dadi Uploaded biasa minangka asil saka kompilasi). Amarga iki, kita bisa kanthi gampang nggawe assignment menyang variabel Object[] arraying baris pisanan saka cara - jinis wis dibusak saka sheets kita! Lan saiki kita duwe variabel saka jinis Object[], ngendi kita bisa nambah apa wae - kabeh obyek ing Jawa warisan saka Object! Saiki kita mung duwe array saka sheets string. Nanging thanks kanggo nggunakake varargslan erasure saka jinis, kita bisa kanthi gampang nambah sheet saka nomer kanggo wong-wong mau, kang kita apa. Akibaté, kita ngrusak tumpukan kanthi nyampur obyek saka macem-macem jinis. Asil bakal dadi pangecualian sing padha ClassCastExceptionnalika nyoba maca senar saka array. Output konsol:

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
Iki minangka akibat sing ora dikarepke sing bisa diakibatake nggunakake mekanisme sing katon prasaja varargs:) Lan ing kene kuliah kita dina iki rampung. Aja lali ngrampungake sawetara masalah, lan yen sampeyan duwe wektu lan tenaga, sinau literatur tambahan. " Jawa efektif " ora bakal diwaca dhewe! :) Sampai ketemu!
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION