CodeGym /జావా బ్లాగ్ /యాదృచ్ఛికంగా /జెనరిక్స్‌తో పనిచేసేటప్పుడు వరార్గ్‌లను ఉపయోగించడం
John Squirrels
స్థాయి
San Francisco

జెనరిక్స్‌తో పనిచేసేటప్పుడు వరార్గ్‌లను ఉపయోగించడం

సమూహంలో ప్రచురించబడింది
హాయ్! నేటి పాఠంలో, మేము జెనరిక్స్ అధ్యయనం కొనసాగిస్తాము. ఇది జరిగినప్పుడు, ఇది పెద్ద అంశం, కానీ దానిని నివారించడం లేదు — ఇది భాషలో చాలా ముఖ్యమైన భాగం :) మీరు ఒరాకిల్ డాక్యుమెంటేషన్‌ను జెనరిక్స్‌పై అధ్యయనం చేసినప్పుడు లేదా ఆన్‌లైన్ ట్యుటోరియల్‌లను చదివినప్పుడు, మీరు రీఫైబుల్ కాని రకాలు మరియు పునర్వినియోగపరచదగిన రకాలు . రీఫైయబుల్ రకం అనేది రన్‌టైమ్‌లో సమాచారం పూర్తిగా అందుబాటులో ఉండే రకం. జావాలో, ఇటువంటి రకాలు ఆదిమలు, ముడి రకాలు మరియు నాన్-జెనరిక్ రకాలు ఉన్నాయి. దీనికి విరుద్ధంగా, నాన్-రీఫైబుల్ రకాలు అంటే సమాచారం తొలగించబడిన మరియు రన్‌టైమ్‌లో ప్రాప్యత చేయలేని రకాలు. ఇది జరిగినప్పుడు, ఇవి జెనరిక్స్ - List<String>, List<Integer>, మొదలైనవి.

మార్గం ద్వారా, varargs అంటే ఏమిటో మీకు గుర్తుందా?

ఒకవేళ మీరు మరచిపోయినట్లయితే, ఇది వేరియబుల్-పొడవు వాదన. మన పద్ధతికి ఎన్ని వాదనలు పంపబడతాయో మనకు తెలియని పరిస్థితులలో అవి ఉపయోగపడతాయి. ఉదాహరణకు, మేము ఒక sumపద్ధతిని కలిగి ఉన్న కాలిక్యులేటర్ తరగతిని కలిగి ఉంటే. పద్ధతి sum()2 సంఖ్యలు, లేదా 3, లేదా 5 లేదా మీకు నచ్చినన్ని అందుకోవచ్చు. sum()సాధ్యమయ్యే ప్రతి వాదనల కోసం పద్ధతిని ఓవర్‌లోడ్ చేయడం చాలా వింతగా ఉంటుంది . బదులుగా, మనం ఇలా చేయవచ్చు:

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));
   }
}
కన్సోల్ అవుట్‌పుట్:

15
11
జనరిక్స్‌తో కలిపి varargsని ఉపయోగిస్తున్నప్పుడు కొన్ని ముఖ్యమైన లక్షణాలు ఉన్నాయని ఇది మాకు చూపుతుంది. కింది కోడ్‌ను చూద్దాం:

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")
       );
   }
}
పద్ధతి ఇన్‌పుట్ a మరియు ఎన్ని ఆబ్జెక్ట్‌లను addAll()తీసుకుంటుంది , ఆపై అది ఈ అన్ని వస్తువులను జాబితాకు జోడిస్తుంది. పద్ధతిలో , మేము మా పద్ధతిని రెండుసార్లు పిలుస్తాము . మొదటి సందర్భంలో, మేము రెండు సాధారణ తీగలను జోడిస్తాము . ఇక్కడ ప్రతిదీ క్రమంలో ఉంది. రెండవ సందర్భంలో, మేము రెండు వస్తువులను జోడించాము . కానీ ఇక్కడ మేము ఊహించని విధంగా హెచ్చరికను అందుకుంటాము: List<E>Emain()addAll()ListPair<String, String>List

Unchecked generics array creation for varargs parameter
అంటే ఏమిటి? మనకు ఎందుకు హెచ్చరిక వస్తుంది మరియు దాని గురించి ఎందుకు ప్రస్తావించబడింది array? అన్నింటికంటే, మా కోడ్‌కు ఒక array! రెండవ కేసుతో ప్రారంభిద్దాం. కంపైలర్ వేరియబుల్-లెంగ్త్ ఆర్గ్యుమెంట్ (varargs)ని శ్రేణిగా మారుస్తుంది కాబట్టి హెచ్చరిక శ్రేణిని ప్రస్తావిస్తుంది. మరో మాటలో చెప్పాలంటే, మా పద్ధతి యొక్క సంతకం addAll():

public static <E> void addAll(List<E> list, E... array)
ఇది వాస్తవానికి ఇలా కనిపిస్తుంది:

public static <E> void addAll(List<E> list, E[] array)
అంటే, పద్ధతిలో main(), కంపైలర్ మన కోడ్‌ని ఇలా మారుస్తుంది:

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") 
        } 
   ); 
}
శ్రేణి Stringబాగానే ఉంది. కానీ ఒక Pair<String, String>శ్రేణి కాదు. సమస్య ఏమిటంటే అది Pair<String, String>పునర్నిర్మించలేని రకం. సంకలనం సమయంలో, టైప్ ఆర్గ్యుమెంట్స్ (<స్ట్రింగ్, స్ట్రింగ్>) గురించిన మొత్తం సమాచారం తొలగించబడుతుంది. జావాలో పునర్నిర్మించలేని రకం శ్రేణులను సృష్టించడం అనుమతించబడదు . మీరు జత<స్ట్రింగ్, స్ట్రింగ్> శ్రేణిని మాన్యువల్‌గా సృష్టించడానికి ప్రయత్నిస్తే మీరు దీన్ని చూడవచ్చు

public static void main(String[] args) {

   // Compilation error Generic array creation
  Pair<String, String>[] array = new Pair<String, String>[10];
}
కారణం స్పష్టంగా ఉంది: రకం భద్రత. మీరు గుర్తుచేసుకున్నట్లుగా, శ్రేణిని సృష్టించేటప్పుడు, శ్రేణి ఏ వస్తువులను (లేదా ఆదిమాంశాలు) నిల్వ చేస్తుందో మీరు ఖచ్చితంగా పేర్కొనాలి.

int array[] = new int[10];
మా మునుపటి పాఠాల్లో ఒకదానిలో, మేము టైప్ ఎరేజర్‌ని వివరంగా పరిశీలించాము. Pairఈ సందర్భంలో, టైప్ ఎరేజర్ వల్ల వస్తువులు జతలను నిల్వ చేసే సమాచారాన్ని మనం కోల్పోతాము <String, String>. శ్రేణిని సృష్టించడం సురక్షితం కాదు. varargs మరియు జెనరిక్స్‌తో కూడిన పద్ధతులను ఉపయోగిస్తున్నప్పుడు , టైప్ ఎరేజర్ మరియు అది ఎలా పని చేస్తుందో గుర్తుంచుకోండి. మీరు వ్రాసిన కోడ్ గురించి మీకు ఖచ్చితంగా తెలిస్తే మరియు దాని వల్ల ఎటువంటి సమస్యలు ఉండవని తెలిస్తే, మీరు ఉల్లేఖనాలను ఉపయోగించి varargs-సంబంధిత హెచ్చరికలను ఆఫ్ చేయవచ్చు . @SafeVarargs

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

   for (E element : array) {
       list.add(element);
   }
}
మీరు ఈ ఉల్లేఖనాన్ని మీ పద్ధతికి జోడిస్తే, మేము ముందుగా ఎదుర్కొన్న హెచ్చరిక కనిపించదు. జనరిక్స్‌తో వరార్గ్‌లను ఉపయోగించినప్పుడు సంభవించే మరో సమస్య కుప్ప కాలుష్యం. జెనరిక్స్‌తో పనిచేసేటప్పుడు వరార్గ్‌లను ఉపయోగించడం - 3కుప్ప కాలుష్యం క్రింది పరిస్థితులలో సంభవించవచ్చు:

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));
   }
}
కన్సోల్ అవుట్‌పుట్:

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
సరళంగా చెప్పాలంటే, Aకుప్పలో ఉండే వస్తువులు కుప్పగా ఉండటాన్ని కుప్ప కాలుష్యం అంటారు, అయితే Bటైప్ సేఫ్టీకి సంబంధించిన ఎర్రర్‌ల కారణంగా రకం వస్తువులు అక్కడ ముగుస్తాయి. మా ఉదాహరణలో, ఇది ఖచ్చితంగా జరుగుతుంది. ముందుగా, మేము ముడి వేరియబుల్‌ని సృష్టించాము మరియు దానికి numbersసాధారణ సేకరణ ( )ని కేటాయించాము . అప్పుడు మేము సేకరణకు ArrayList<Number>సంఖ్యను జోడించాము .1

List<String> strings = numbers;
ఈ లైన్‌లో, కంపైలర్ " చెక్ చేయని అసైన్‌మెంట్... " హెచ్చరికను జారీ చేయడం ద్వారా సాధ్యమయ్యే లోపాల గురించి మమ్మల్ని హెచ్చరించడానికి ప్రయత్నించింది, కానీ మేము దానిని విస్మరించాము. List<String>మేము రకం యొక్క సాధారణ సేకరణను సూచించే రకం యొక్క సాధారణ వేరియబుల్‌తో ముగుస్తుంది ArrayList<Number>. స్పష్టంగా, ఈ పరిస్థితి ఇబ్బందులకు దారి తీస్తుంది! మరియు అది చేస్తుంది. మా కొత్త వేరియబుల్ ఉపయోగించి, మేము సేకరణకు స్ట్రింగ్‌ను జోడిస్తాము. మేము ఇప్పుడు కుప్ప కాలుష్యాన్ని కలిగి ఉన్నాము - మేము పారామితి చేయబడిన సేకరణకు ఒక సంఖ్యను జోడించి ఆపై స్ట్రింగ్‌ను జోడించాము. కంపైలర్ మమ్మల్ని హెచ్చరించాడు, కానీ మేము దాని హెచ్చరికను పట్టించుకోలేదు. ఫలితంగా, ClassCastExceptionప్రోగ్రామ్ నడుస్తున్నప్పుడు మాత్రమే మనకు లభిస్తుంది. కాబట్టి దీనికి వరార్గ్స్‌తో సంబంధం ఏమిటి? జెనరిక్స్‌తో వరర్గ్‌లను ఉపయోగించడం వల్ల కుప్పల కాలుష్యానికి సులభంగా దారితీయవచ్చు. ఇక్కడ ఒక సాధారణ ఉదాహరణ:

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);
   }
}
ఏమి జరుగుతుంది ఇక్కడ? టైప్ ఎరేజర్ కారణంగా, మా వేరియబుల్-లెంగ్త్ ఆర్గ్యుమెంట్

List<String>...stringsLists
జాబితాల శ్రేణిగా మారుతుంది, అనగా List[], తెలియని రకం వస్తువులు (సంకలనం సమయంలో varargs సాధారణ శ్రేణిగా మారుతుందని మర్చిపోవద్దు). దీని కారణంగా, మేము దానిని పద్ధతి యొక్క మొదటి పంక్తిలోని వేరియబుల్‌కు సులభంగా కేటాయించవచ్చు Object[] array— మా జాబితాలలోని వస్తువుల రకం తొలగించబడింది! మరియు ఇప్పుడు మనకు Object[]వేరియబుల్ ఉంది, దానికి మనం దేనినైనా జోడించవచ్చు, ఎందుకంటే జావాలోని అన్ని వస్తువులు వారసత్వంగా పొందుతాయి Object! మొదట, మేము స్ట్రింగ్‌ల జాబితాల శ్రేణిని మాత్రమే కలిగి ఉన్నాము. కానీ టైప్ ఎరేజర్ మరియు varargs యొక్క మా వినియోగానికి ధన్యవాదాలు, మనం చేసే సంఖ్యల జాబితాను సులభంగా జోడించవచ్చు. ఫలితంగా, మేము వివిధ రకాల వస్తువులను కలపడం ద్వారా కుప్పను కలుషితం చేస్తాము. ClassCastExceptionమేము శ్రేణి నుండి స్ట్రింగ్‌ను చదవడానికి ప్రయత్నించినప్పుడు ఫలితం మరొకటి ఉంటుంది . కన్సోల్ అవుట్‌పుట్:

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
అటువంటి ఊహించని పరిణామాలు varargs ను ఉపయోగించడం వలన సంభవించవచ్చు, ఇది ఒక సాధారణ మెకానిజం :) మరియు దానితో, నేటి పాఠం ముగుస్తుంది. కొన్ని పనులను పరిష్కరించడం మర్చిపోవద్దు మరియు మీకు సమయం మరియు శక్తి ఉంటే, అదనపు పఠనాన్ని అధ్యయనం చేయండి. " ఎఫెక్టివ్ జావా " స్వయంగా చదవదు! :) మరల సారి వరకు!
వ్యాఖ్యలు
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION