CodeGym /Blog Jawa /Acak /Nggunakake varargs nalika nggarap generik
John Squirrels
tingkat
San Francisco

Nggunakake varargs nalika nggarap generik

Diterbitake ing grup
Hi! Ing wulangan dina iki, kita bakal terus sinau babagan generik. Kaya sing kedadeyan, iki minangka topik gedhe, nanging ora bisa dihindari - iki minangka bagean basa sing penting banget :) Nalika sampeyan sinau dokumentasi Oracle babagan generik utawa maca tutorial online, sampeyan bakal nemokake istilah jinis sing ora bisa dibaleni lan jinis reifiable . Jinis reifiable yaiku jinis sing informasi kasedhiya nalika runtime. Ing Jawa, jinis kasebut kalebu jinis primitif, jinis mentah, lan jinis non-generik. Ing kontras, jinis non-reifiable jinis sing informasi dibusak lan dadi ora bisa diakses nalika runtime. Kaya mengkono, iki generik - List<String>, List<Integer>, etc.

Ngomong-ngomong, apa sampeyan kelingan apa varargs?

Yen sampeyan kelalen, iki minangka argumen variabel. Iku migunani ing kahanan sing kita ora ngerti carane akeh bantahan bisa liwati kanggo cara kita. Contone, yen kita duwe kelas kalkulator sing duwe summetode. Cara kasebut sum()bisa nampa 2 nomer, utawa 3, utawa 5, utawa akeh sing disenengi. Iku bakal banget aneh kanggo kakehan sum()cara kanggo saben nomer bisa bantahan. 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
Iki nuduhake yen ana sawetara fitur penting nalika nggunakake varargs ing kombinasi karo generik. Ayo ndeleng kode ing ngisor 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>(), // This is okay
               "Leonardo da Vinci",
               "Vasco de Gama"
       );

       // but here we get a warning
       addAll(new ArrayList<Pair<String, String>>(),
               new Pair<String, String>("Leonardo", "da Vinci"),
               new Pair<String, String>("Vasco", "de Gama")
       );
   }
}
Cara addAll()njupuk minangka input a List<E>lan nomer Eobyek, lan banjur nambah kabeh obyek iki kanggo dhaftar. Ing main()metode kasebut, kita nelpon addAll()metode kita kaping pindho. Ing kasus sing sepisanan, kita nambah rong senar biasa menyang List. Kabeh ana ing kene. Ing kasus kapindho, kita nambah rong Pair<String, String>obyek menyang List. Nanging ing kene kita ora sengaja nampa peringatan:

Unchecked generics array creation for varargs parameter
Apa tegese? Napa kita entuk bebaya lan kenapa ana sing nyebutake array? Sawise kabeh, kode kita ora duwe array! Ayo dadi miwiti karo kasus kapindho. Peringatan kasebut nyebutake array amarga compiler ngowahi argumen variabel-dawa (varargs) dadi array. Ing tembung liyane, tandha addAll()cara kita yaiku:

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 main()metode kasebut, kompiler 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") 
        } 
   ); 
}
A Stringarray mung apik. Nanging Pair<String, String>array ora. Masalah iku Pair<String, String>jinis non-reifiable. Sajrone kompilasi, kabeh informasi babagan argumen jinis (<String, String>) bakal dibusak. Nggawe array saka jinis non-reifiable ora diijini ing Jawa . Sampeyan bisa ndeleng iki yen sampeyan nyoba nggawe kanthi manual pasangan<String, String> array

public static void main(String[] args) {

   // Compilation error Generic array creation
  Pair<String, String>[] array = new Pair<String, String>[10];
}
Alesané ketok: jinis safety. Nalika sampeyan kelingan, nalika nggawe array, sampeyan kudu nemtokake obyek (utawa primitif) sing bakal disimpen ing array.

int array[] = new int[10];
Ing salah sawijining pawulangan sadurunge, kita mriksa kanthi rinci babagan mbusak jinis. Ing kasus iki, jinis erasure nyebabake kita ilang informasi sing Pairobyek disimpen <String, String>pasangan. Nggawe array bakal ora aman. Nalika nggunakake metode sing kalebu varargs lan generik, mesthine elinga babagan mbusak jinis lan cara kerjane. Yen sampeyan pancen yakin babagan kode sing wis ditulis lan ngerti yen ora bakal nyebabake masalah, sampeyan bisa mateni bebaya sing gegandhengan karo varargs 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 kedadeyan nalika nggunakake varargs karo generik yaiku polusi tumpukan. Nggunakake varargs nalika nggarap generik - 3Polusi tumpukan bisa kedadeyan ing kahanan ing ngisor iki:

import java.util.ArrayList;
import java.util.List;

public class Main {

   static List<String> polluteHeap() {
       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 = polluteHeap();

       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 yaiku nalika obyek saka jinis Akudu ana ing tumpukan, nanging obyek saka jinis Bbakal ana amarga kesalahan sing ana gandhengane karo safety jinis. Ing conto kita, iki persis apa sing kedadeyan. Kaping pisanan, kita nggawe numbersvariabel mentah lan menehi koleksi umum ( ArrayList<Number>) menyang. Banjur kita nambah nomer 1menyang koleksi.

List<String> strings = numbers;
Ing baris iki, compiler nyoba kanggo ngelekake kita saka kamungkinan kasalahan dening nerbitake " Tugas ora dicenthang ... ", nanging kita ora digatèkaké. Kita mungkasi karo jinis variabel umum List<String>sing nuduhake koleksi jinis umum ArrayList<Number>. Cetha, kahanan iki bisa nyebabake masalah! Lan mengkono iku. Nggunakake variabel anyar kita, kita nambah string menyang koleksi. Saiki kita duwe polusi tumpukan - kita nambahake nomer banjur string menyang koleksi parametrized. Compiler ngelingake kita, nanging kita ora nggatekake bebaya kasebut. Akibaté, kita entuk ClassCastExceptionmung nalika program lagi mlaku. Dadi apa hubungane karo varargs? Nggunakake varargs karo generik bisa gampang nyebabake polusi numpuk. Punika conto prasaja:

import java.util.Arrays;
import java.util.List;

public class Main {

   static void polluteHeap(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");

       polluteHeap(cars1, cars2);
   }
}
Apa sing kedadeyan ing kene? Amarga jinis erasure, argumen dawa variabel kita

List<String>...stringsLists
dadi Uploaded dhaftar, IE List[], obyek saka jinis dingerteni (aja lali sing varargs dadi Uploaded biasa sak kompilasi). Amarga iki, kita bisa kanthi gampang nemtokake variabel kasebut Object[] arraying baris pisanan metode - jinis obyek ing dhaptar kita wis dibusak! Lan saiki kita duwe Object[]variabel, sing bisa ditambahake apa wae, amarga kabeh obyek ing Jawa duwe warisan Object! Kaping pisanan, kita mung duwe dhaptar dhaptar senar. Nanging thanks kanggo jinis erasure lan nggunakake varargs, kita bisa kanthi gampang nambah dhaptar nomer, kang kita nindakake. Akibaté, kita ngrusak tumpukan kanthi nyampur obyek saka macem-macem jinis. Asil bakal liyane ClassCastExceptionnalika kita nyoba maca senar saka array. Output konsol:

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
Akibat sing ora dikarepke kuwi bisa disebabake nggunakake varargs, mekanisme ketoke prasaja :) Lan karo iku, pawulangan dina iki rampung. Aja lali ngrampungake sawetara tugas, lan yen sampeyan duwe wektu lan tenaga, sinau sawetara maca tambahan. " Jawa efektif " ora bakal diwaca dhewe! :) Nganti wektu sabanjure!
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION