CodeGym /జావా బ్లాగ్ /యాదృచ్ఛికంగా /స్థానిక పద్ధతిలో అంతర్గత తరగతులు
John Squirrels
స్థాయి
San Francisco

స్థానిక పద్ధతిలో అంతర్గత తరగతులు

సమూహంలో ప్రచురించబడింది
హాయ్! మరొక రకమైన సమూహ తరగతుల గురించి మాట్లాడుదాం. నేను స్థానిక తరగతుల గురించి మాట్లాడుతున్నాను (పద్ధతి-స్థానిక అంతర్గత తరగతులు). డైవింగ్ చేయడానికి ముందు, మేము ముందుగా సమూహ తరగతుల నిర్మాణంలో వారి స్థానాన్ని గుర్తుంచుకోవాలి. స్థానిక పద్ధతిలో అంతర్గత తరగతులు - 2మా రేఖాచిత్రం నుండి, స్థానిక తరగతులు అంతర్గత తరగతుల ఉపజాతి అని మనం చూడవచ్చు, దాని గురించి మేము మునుపటి విషయాలలో వివరంగా మాట్లాడాము . అయినప్పటికీ, స్థానిక తరగతులకు సాధారణ అంతర్గత తరగతుల నుండి అనేక ముఖ్యమైన లక్షణాలు మరియు తేడాలు ఉన్నాయి. ప్రధాన విషయం వారి డిక్లరేషన్‌లో ఉంది: స్థానిక తరగతి కోడ్ యొక్క బ్లాక్‌లో మాత్రమే ప్రకటించబడుతుంది. చాలా తరచుగా, ఈ డిక్లరేషన్ బాహ్య తరగతి యొక్క కొన్ని పద్ధతిలో ఉంటుంది. ఉదాహరణకు, ఇది ఇలా ఉండవచ్చు:

public class PhoneNumberValidator {

   public void validatePhoneNumber(String number) {

        class PhoneNumber {

           private String phoneNumber;

           public PhoneNumber() {
               this.phoneNumber = number;
           }

           public String getPhoneNumber() {
               return phoneNumber;
           }

           public void setPhoneNumber(String phoneNumber) {
               this.phoneNumber = phoneNumber;
           }
       }

       // ...number validation code
   }
}
ముఖ్యమైనది!మీరు Java 7ని ఇన్‌స్టాల్ చేసి ఉంటే, IDEAలో అతికించినప్పుడు ఈ కోడ్ కంపైల్ చేయబడదు. మేము పాఠం చివరిలో దీనికి కారణాల గురించి మాట్లాడుతాము. సంక్షిప్తంగా, స్థానిక తరగతులు ఎలా పని చేస్తాయి అనేది భాష యొక్క సంస్కరణపై ఎక్కువగా ఆధారపడి ఉంటుంది. ఈ కోడ్ మీ కోసం కంపైల్ చేయకపోతే, మీరు IDEAలోని భాషా సంస్కరణను జావా 8కి మార్చవచ్చు లేదా పదాన్ని finalపద్ధతి పరామితికి జోడించవచ్చు, తద్వారా ఇది ఇలా కనిపిస్తుంది: validatePhoneNumber(final String number). ఆ తరువాత, ప్రతిదీ పని చేస్తుంది. ఇది ఫోన్ నంబర్‌లను ధృవీకరించే చిన్న ప్రోగ్రామ్. దీని validatePhoneNumber()పద్ధతి స్ట్రింగ్‌ను ఇన్‌పుట్‌గా తీసుకుంటుంది మరియు అది ఫోన్ నంబర్ కాదా అని నిర్ణయిస్తుంది. మరియు ఈ పద్ధతి లోపల, మేము మా స్థానిక PhoneNumberతరగతిని ప్రకటించాము. ఎందుకు అని మీరు సహేతుకంగా అడగవచ్చు. మేము ఒక పద్ధతిలో తరగతిని ఎందుకు ఖచ్చితంగా ప్రకటిస్తాము? సాధారణ అంతర్గత తరగతిని ఎందుకు ఉపయోగించకూడదు? నిజమే, మేము తయారు చేయగలముPhoneNumberతరగతి మరియు అంతర్గత తరగతి. కానీ తుది పరిష్కారం మీ ప్రోగ్రామ్ యొక్క నిర్మాణం మరియు ప్రయోజనంపై ఆధారపడి ఉంటుంది. అంతర్గత తరగతుల పాఠం నుండి మన ఉదాహరణను గుర్తుచేసుకుందాం:

public class Bicycle {

   private String model;
   private int maxWeight;

   public Bicycle(String model, int maxWeight) {
       this.model = model;
       this.maxWeight = maxWeight;
   }
  
   public void start() {
       System.out.println("Let's go!");
   }

   public class HandleBar {

       public void right() {
           System.out.println("Steer right!");
       }

       public void left() {

           System.out.println("Steer left!");
       }
   }
}
అందులో, మేము HandleBarబైక్ యొక్క అంతర్గత తరగతిని తయారు చేసాము. తేడా ఏమిటి? అన్నింటిలో మొదటిది, తరగతిని ఉపయోగించే విధానం భిన్నంగా ఉంటుంది. మొదటి ఉదాహరణలోని తరగతి కంటే రెండవ ఉదాహరణలోని తరగతి HandleBarమరింత సంక్లిష్టమైన అంశం PhoneNumber. ముందుగా, HandleBarపబ్లిక్ rightమరియు leftమెథడ్స్ ఉన్నాయి (ఇవి సెట్టర్స్/గెటర్స్ కాదు). రెండవది, మనకు ఎక్కడ అవసరమో మరియు దాని బయటి తరగతిని ముందుగానే అంచనా వేయడం అసాధ్యం Bicycle. ఒకే ప్రోగ్రామ్‌లో కూడా డజన్ల కొద్దీ వేర్వేరు స్థలాలు మరియు పద్ధతులు ఉండవచ్చు. కానీ తరగతితో PhoneNumber, ప్రతిదీ చాలా సులభం. మా కార్యక్రమం చాలా సులభం. దీనికి ఒకే ఒక ప్రయోజనం ఉంది: నంబర్ చెల్లుబాటు అయ్యే ఫోన్ నంబర్ కాదా అని తనిఖీ చేయడం. చాలా సందర్భాలలో, మాPhoneNumberValidatorఒక స్వతంత్ర ప్రోగ్రామ్ కూడా కాదు, కానీ పెద్ద ప్రోగ్రామ్ కోసం అధికార లాజిక్‌లో భాగం. ఉదాహరణకు, వినియోగదారులు సైన్ అప్ చేసినప్పుడు వివిధ వెబ్‌సైట్‌లు తరచుగా ఫోన్ నంబర్‌ను అడుగుతాయి. మీరు నంబర్‌లకు బదులుగా కొన్ని అర్ధంలేని విషయాలను నమోదు చేస్తే, వెబ్‌సైట్ లోపాన్ని నివేదిస్తుంది: "ఇది ఫోన్ నంబర్ కాదు!" అటువంటి వెబ్‌సైట్ డెవలపర్‌లు (లేదా బదులుగా, దాని వినియోగదారు అధికార యంత్రాంగం) మా మాదిరిగానే ఏదైనా చేర్చవచ్చుPhoneNumberValidatorవారి కోడ్‌లో. మరో మాటలో చెప్పాలంటే, మేము ఒక పద్ధతితో ఒక బాహ్య తరగతిని కలిగి ఉన్నాము, ఇది ప్రోగ్రామ్‌లో ఒకే స్థలంలో ఉపయోగించబడుతుంది మరియు మరెక్కడా ఉండదు. మరియు అది ఉపయోగించినట్లయితే, దానిలో ఏమీ మారదు: ఒక పద్ధతి దాని పనిని చేస్తుంది - మరియు అంతే. ఈ సందర్భంలో, అన్ని తర్కాలు ఒకే పద్ధతిలో సేకరించబడినందున, అక్కడ అదనపు తరగతిని చేర్చడం చాలా సౌకర్యవంతంగా మరియు సరైనదిగా ఉంటుంది. దీనికి గెట్టర్ మరియు సెట్టర్ తప్ప దాని స్వంత పద్ధతులు లేవు. వాస్తవానికి, మనకు కన్స్ట్రక్టర్ నుండి డేటా మాత్రమే అవసరం. ఇది ఇతర పద్ధతులలో ప్రమేయం లేదు. దీని ప్రకారం, అది ఉపయోగించిన ఏకైక పద్ధతి వెలుపల దాని గురించి సమాచారాన్ని తీసుకోవడానికి ఎటువంటి కారణం లేదు. మేము స్థానిక తరగతిని ఒక పద్ధతిలో ప్రకటించే ఉదాహరణను కూడా ఇచ్చాము, కానీ ఇది మాత్రమే ఎంపిక కాదు. ఇది కేవలం కోడ్ బ్లాక్‌లో ప్రకటించవచ్చు:

public class PhoneNumberValidator {
  
   {
       class PhoneNumber {

           private String phoneNumber;

           public PhoneNumber(String phoneNumber) {
               this.phoneNumber = phoneNumber;
           }
       }

   }

   public void validatePhoneNumber(String phoneNumber) {

      
       // ...number validation code
   }
}
లేదా లూప్‌లో కూడా for!

public class PhoneNumberValidator {
  

   public void validatePhoneNumber(String phoneNumber) {

       for (int i = 0; i < 10; i++) {

           class PhoneNumber {

               private String phoneNumber;

               public PhoneNumber(String phoneNumber) {
                   this.phoneNumber = phoneNumber;
               }
           }
          
           // ...some logic
       }

       // ...number validation code
   }
}
కానీ అలాంటి కేసులు చాలా అరుదు. చాలా సందర్భాలలో, డిక్లరేషన్ పద్ధతి లోపల జరుగుతుంది. కాబట్టి, మేము ప్రకటనలను కనుగొన్నాము మరియు మేము "తత్వశాస్త్రం" గురించి కూడా మాట్లాడాము :) అంతర్గత తరగతులతో పోల్చితే స్థానిక తరగతులకు ఏ అదనపు లక్షణాలు మరియు తేడాలు ఉన్నాయి? స్థానిక తరగతికి చెందిన వస్తువును అది ప్రకటించబడిన పద్ధతి లేదా బ్లాక్ వెలుపల సృష్టించబడదు. generatePhoneNumber()యాదృచ్ఛిక ఫోన్ నంబర్‌ను రూపొందించి, వస్తువును తిరిగి ఇచ్చే పద్ధతి మనకు అవసరమని ఊహించండి PhoneNumber. మా ప్రస్తుత పరిస్థితిలో, మేము మా వాలిడేటర్ క్లాస్‌లో అటువంటి పద్ధతిని సృష్టించలేము:

public class PhoneNumberValidator {

   public void validatePhoneNumber(String number) {

        class PhoneNumber {

           private String phoneNumber;

           public PhoneNumber() {
               this.phoneNumber = number;
           }

           public String getPhoneNumber() {
               return phoneNumber;
           }

           public void setPhoneNumber(String phoneNumber) {
               this.phoneNumber = phoneNumber;
           }
       }

       // ...number validation code
   }

   // Error! The compiler does not recognize the PhoneNumber class
   public PhoneNumber generatePhoneNumber() {

   }

}
స్థానిక తరగతుల యొక్క మరొక ముఖ్యమైన లక్షణం స్థానిక వేరియబుల్స్ మరియు మెథడ్ పారామితులను యాక్సెస్ చేయగల సామర్థ్యం. ఒకవేళ మీరు మరచిపోయినట్లయితే, ఒక పద్ధతిలో డిక్లేర్ చేయబడిన వేరియబుల్‌ని "స్థానిక" వేరియబుల్ అంటారు. అంటే, మనం మెథడ్ String usCountryCodeలోపల లోకల్ వేరియబుల్‌ని క్రియేట్ చేస్తే validatePhoneNumber()కొన్ని కారణాల వల్ల, మనం దానిని లోకల్ PhoneNumberక్లాస్ నుండి యాక్సెస్ చేయవచ్చు. అయినప్పటికీ, ప్రోగ్రామ్‌లో ఉపయోగించిన భాష యొక్క సంస్కరణపై ఆధారపడిన సూక్ష్మబేధాలు చాలా ఉన్నాయి. పాఠం ప్రారంభంలో, ఉదాహరణలలో ఒకదానికి సంబంధించిన కోడ్ జావా 7లో కంపైల్ చేయబడదని మేము గుర్తించాము, గుర్తుందా? ఇప్పుడు దీనికి గల కారణాలను పరిశీలిద్దాం :) జావా 7లో, స్థానిక తరగతి వారు పద్ధతిలో ఉన్నట్లుగా ప్రకటించబడితే మాత్రమే స్థానిక వేరియబుల్ లేదా మెథడ్ పారామీటర్‌ను యాక్సెస్ చేయగలదు :final

public void validatePhoneNumber(String number) {

   String usCountryCode = "+1";

   class PhoneNumber {

       private String phoneNumber;

       // Error! The method parameter must be declared as final!
       public PhoneNumber() {
           this.phoneNumber = number;
       }

       public void printUsCountryCode() {

           // Error! The local variable must be declared as final!
           System.out.println(usCountryCode);
       }

   }

   // ...number validation code
}
ఇక్కడ కంపైలర్ రెండు లోపాలను సృష్టిస్తుంది. మరియు ఇక్కడ ప్రతిదీ క్రమంలో ఉంది:

public void validatePhoneNumber(final String number) {

   final String usCountryCode = "+1";

    class PhoneNumber {

       private String phoneNumber;

       
       public PhoneNumber() {
           this.phoneNumber = number;
       }

       public void printUsCountryCode() {

           System.out.println(usCountryCode);
       }

    }

   // ...number validation code
}
పాఠం ప్రారంభం నుండి కోడ్ ఎందుకు కంపైల్ చేయబడదని ఇప్పుడు మీకు తెలుసు: జావా 7లో, స్థానిక తరగతికి finalమెథడ్ పారామీటర్‌లు మరియు finalలోకల్ వేరియబుల్స్ మాత్రమే యాక్సెస్ ఉంటుంది. జావా 8లో, స్థానిక తరగతుల ప్రవర్తన మారింది. భాష యొక్క ఈ సంస్కరణలో, స్థానిక తరగతికి finalస్థానిక వేరియబుల్స్ మరియు పారామీటర్‌లకు మాత్రమే కాకుండా, ఉన్న వాటికి కూడా యాక్సెస్ ఉంటుంది effective-final. Effective-finalప్రారంభమైనప్పటి నుండి విలువ మారని వేరియబుల్. usCountryCodeఉదాహరణకు, జావా 8లో, కన్సోల్‌లో వేరియబుల్ కాకపోయినా సులభంగా ప్రదర్శించవచ్చు final. ముఖ్యమైన విషయం ఏమిటంటే దాని విలువ మారదు. కింది ఉదాహరణలో, ప్రతిదీ తప్పక పని చేస్తుంది:

public void validatePhoneNumber(String number) {

  String usCountryCode = "+1";

    class PhoneNumber {

       public void printUsCountryCode() {

           // Java 7 would produce an error here
           System.out.println(usCountryCode);
       }

    }

   // ...number validation code
}
కానీ మనం ప్రారంభించిన వెంటనే వేరియబుల్ విలువను మార్చినట్లయితే, కోడ్ కంపైల్ చేయబడదు.

public void validatePhoneNumber(String number) {

  String usCountryCode = "+1";
  usCountryCode = "+8";

    class PhoneNumber {

       public void printUsCountryCode() {

           // Error!
           System.out.println(usCountryCode);
       }

    }

   // ...number validation code
}
స్థానిక తరగతి అంతర్గత తరగతి భావన యొక్క ఉపజాతి అని ఆశ్చర్యపోనవసరం లేదు! వాటికి సాధారణ లక్షణాలు కూడా ఉన్నాయి. స్థానిక తరగతికి అన్ని (ప్రైవేట్ కూడా) ఫీల్డ్‌లు మరియు బాహ్య తరగతి యొక్క పద్ధతులకు ప్రాప్యత ఉంది: స్టాటిక్ మరియు నాన్-స్టాటిక్ రెండూ. String phoneNumberRegexఉదాహరణకు, మన వాలిడేటర్ క్లాస్‌కి స్టాటిక్ ఫీల్డ్‌ని జోడిద్దాం :

public class PhoneNumberValidator {

   private static String phoneNumberRegex = "[^0-9]";

   public void validatePhoneNumber(String phoneNumber) {
       class PhoneNumber {
          
           // ......
       }
   }
}
ఈ స్టాటిక్ వేరియబుల్ ఉపయోగించి ధ్రువీకరణ జరుగుతుంది. [^0-9]ఆమోదించబడిన స్ట్రింగ్‌లో సాధారణ వ్యక్తీకరణ " " (అంటే 0 నుండి 9 వరకు అంకెలు లేని ఏదైనా అక్షరం) సరిపోలని అక్షరాలు ఉన్నాయో లేదో ఈ పద్ధతి తనిఖీ చేస్తుంది . మనం లోకల్ PhoneNumberక్లాస్ నుండి ఈ వేరియబుల్‌ని సులభంగా యాక్సెస్ చేయవచ్చు. ఉదాహరణకు, పొందే వ్యక్తిని వ్రాయండి:

public String getPhoneNumberRegex() {
  
   return phoneNumberRegex;
}
స్థానిక తరగతులు అంతర్గత తరగతులకు సమానంగా ఉంటాయి, ఎందుకంటే అవి ఏ స్టాటిక్ సభ్యులను నిర్వచించలేవు లేదా ప్రకటించలేవు. స్టాటిక్ మెథడ్స్‌లోని స్థానిక తరగతులు ఎన్‌క్లోజింగ్ క్లాస్‌లోని స్టాటిక్ సభ్యులను మాత్రమే సూచించగలవు. ఉదాహరణకు, మీరు ఎన్‌క్లోజింగ్ క్లాస్ యొక్క వేరియబుల్ (ఫీల్డ్)ని స్టాటిక్‌గా నిర్వచించకపోతే, జావా కంపైలర్ ఒక లోపాన్ని సృష్టిస్తుంది: "స్టాటిక్ కాని వేరియబుల్ స్టాటిక్ కాంటెక్స్ట్ నుండి సూచించబడదు." స్థానిక తరగతులు స్థిరంగా ఉండవు, ఎందుకంటే వాటికి ఎన్‌క్లోజింగ్ బ్లాక్‌లోని ఉదాహరణ సభ్యులకు ప్రాప్యత ఉంది. ఫలితంగా, అవి చాలా రకాల స్టాటిక్ డిక్లరేషన్‌లను కలిగి ఉండవు. మీరు బ్లాక్ లోపల ఇంటర్‌ఫేస్‌ను ప్రకటించలేరు: ఇంటర్‌ఫేస్‌లు అంతర్గతంగా స్థిరంగా ఉంటాయి. ఈ కోడ్ కంపైల్ చేయదు:

public class PhoneNumberValidator {
   public static void validatePhoneNumber(String number) {
       interface I {}
      
       class PhoneNumber implements I{
           private String phoneNumber;

           public PhoneNumber() {
               this.phoneNumber = number;
           }
       }

       // ...number validation code
   }
}
కానీ బయటి తరగతి లోపల ఇంటర్‌ఫేస్ ప్రకటించబడితే, PhoneNumberతరగతి దానిని అమలు చేయగలదు:

public class PhoneNumberValidator {
   interface I {}
  
   public static void validatePhoneNumber(String number) {
      
       class PhoneNumber implements I{
           private String phoneNumber;

           public PhoneNumber() {
               this.phoneNumber = number;
           }
       }

       // ...number validation code
   }
}
స్థానిక తరగతులలో స్టాటిక్ ఇనిషియలైజర్‌లు (ఇనిషియలైజేషన్ బ్లాక్‌లు) లేదా ఇంటర్‌ఫేస్‌లు ప్రకటించబడవు. కానీ స్థానిక తరగతులు స్థిరమైన చరరాశులు ( ) అయితే అవి స్థిరమైన సభ్యులను కలిగి ఉంటాయి static final. మరియు ఇప్పుడు మీరు స్థానిక తరగతుల గురించి తెలుసు, చేసారో! మీరు చూడగలిగినట్లుగా, వారికి సాధారణ అంతర్గత తరగతుల నుండి చాలా తేడాలు ఉన్నాయి. భాష యొక్క నిర్దిష్ట సంస్కరణలు ఎలా పని చేస్తాయో అర్థం చేసుకోవడానికి మేము వాటి లక్షణాలను పరిశోధించవలసి వచ్చింది :) తదుపరి పాఠంలో, మేము అనామక అంతర్గత తరగతుల గురించి మాట్లాడుతాము — సమూహ తరగతుల చివరి సమూహం. మీ చదువులో అదృష్టం! :)
వ్యాఖ్యలు
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION