गैर-स्थिर चर को स्थिर संदर्भ से संदर्भित नहीं किया जा सकता है


288

मैंने यह परीक्षण कोड लिखा है:

class MyProgram
{
    int count = 0;
    public static void main(String[] args)
    {
        System.out.println(count);
    }
}

लेकिन यह निम्नलिखित त्रुटि देता है:

Main.java:6: error: non-static variable count cannot be referenced from a static context
        System.out.println(count);
                           ^

मैं अपने वर्ग चर को पहचानने के लिए अपने तरीके कैसे प्राप्त करूं?


जब भी संभव हो स्थैतिक का उपयोग करने से बचने का प्रयास करें। आप एक संपूर्ण कार्यक्रम, जैसे सभी स्थिर लिख सकते हैंC । लेकिन यह बहुत अच्छा नहीं होगा। जावा का उपयोग करने का प्रयास करें जिस तरह से इसका उपयोग किया जाना चाहिए, एक वस्तु उन्मुख भाषा के रूप में।
एरिक जी। हागस्ट्रॉम

जवाबों:


294

आपको एक वर्ग और उस वर्ग के उदाहरण के बीच के अंतर को समझना होगा। यदि आप सड़क पर एक कार देखते हैं, तो आप तुरंत जानते हैं कि यह एक कार है भले ही आप यह नहीं देख सकते कि कौन सा मॉडल या प्रकार है। ऐसा इसलिए है क्योंकि आप कक्षा "कार" के साथ जो देखते हैं उसकी तुलना करते हैं । वर्ग में सभी कारों के समान है। इसे एक टेम्पलेट या एक विचार के रूप में सोचें।

इसी समय, आपके द्वारा देखी जाने वाली कार क्लास "कार" का एक उदाहरण है क्योंकि इसमें वे सभी गुण हैं जिनकी आप अपेक्षा करते हैं: कोई व्यक्ति इसे चला रहा है, इसमें एक इंजन, पहिए हैं।

तो वर्ग कहता है "सभी कारों का रंग एक है" और उदाहरण कहता है "यह विशिष्ट कार लाल है"।

ऊ दुनिया में, आप वर्ग को परिभाषित करते हैं और कक्षा के अंदर, आप प्रकार के एक क्षेत्र को परिभाषित करते हैं Color। जब कक्षा को त्वरित किया जाता है (जब आप एक विशिष्ट उदाहरण बनाते हैं), तो मेमोरी रंग के लिए आरक्षित होती है और आप इस विशिष्ट उदाहरण को एक रंग दे सकते हैं। चूंकि ये विशेषताएँ विशिष्ट हैं, इसलिए वे गैर-स्थिर हैं।

स्थैतिक क्षेत्र और विधियाँ सभी उदाहरणों के साथ साझा की जाती हैं। वे उन मूल्यों के लिए हैं जो वर्ग के लिए विशिष्ट हैं न कि एक विशिष्ट उदाहरण के लिए। विधियों के लिए, यह आमतौर पर वैश्विक सहायक विधियाँ हैं (जैसे Integer.parseInt())। खेतों के लिए, यह आमतौर पर स्थिरांक होता है (जैसे कार के प्रकार, यानी कुछ ऐसा जहां आपके पास एक सीमित सेट होता है जो अक्सर बदलता नहीं है)।

अपनी समस्या को हल करने के लिए, आपको अपनी कक्षा का एक उदाहरण (ऑब्जेक्ट बनाने) की आवश्यकता है ताकि रनटाइम उदाहरण के लिए मेमोरी को आरक्षित कर सके (अन्यथा, विभिन्न उदाहरण एक दूसरे को अधिलेखित कर देंगे जो आप नहीं चाहते हैं)।

आपके मामले में, इस कोड को शुरुआती ब्लॉक के रूप में आज़माएँ:

public static void main (String[] args)
{
    try
    {
        MyProgram7 obj = new MyProgram7 ();
        obj.run (args);
    }
    catch (Exception e)
    {
        e.printStackTrace ();
    }
}

// instance variables here

public void run (String[] args) throws Exception
{
    // put your code here
}

नई main()विधि उस वर्ग का एक उदाहरण बनाती है जिसमें यह सम्‍मिलित होता है (अजीब लगता है लेकिन चूँकि main()उदाहरण के बजाय कक्षा के साथ बनाया गया है, यह ऐसा कर सकता है) और फिर एक आवृत्ति विधि ( run()) कहता है ।


मैं इस समय हमारे नए सहयोगी को समझा रहा हूं - इस महान स्पष्टीकरण के लिए धन्यवाद। इसे स्वीकार करना चाहिए।
सुपहुपे

83

स्थैतिक क्षेत्र और विधियाँ स्वयं वर्ग से जुड़ी हैं न कि इसके उदाहरण। यदि आपके पास एक वर्ग A, एक 'सामान्य' विधि b, और एक स्थिर विधि है c, और आप aअपनी कक्षा का एक उदाहरण बनाते हैं A, तो कॉल A.c()और a.b()मान्य हैं। विधि c()का कोई विचार नहीं है कि कौन सा उदाहरण जुड़ा हुआ है, इसलिए यह गैर-स्थिर क्षेत्रों का उपयोग नहीं कर सकता है।

आपके लिए समाधान यह है कि आप या तो अपने क्षेत्रों को स्थिर बना लें या अपने तरीकों को गैर-स्थिर बना लें। आप मुख्य तब इस तरह दिख सकते हैं:

class Programm {

    public static void main(String[] args) {
        Programm programm = new Programm();
        programm.start();
    }

    public void start() {
        // can now access non-static fields
    }
}

54

staticएक प्रणाली या चर एक वर्ग के भीतर के जीवन चक्र को संशोधित करता है। एक staticकक्षा लोड होने के समय एक विधि या चर बनाया जाता है। एक विधि या चर जिसे घोषित नहीं किया जाता है staticवह केवल तब बनाया जाता है जब newऑपरेटर के उपयोग से उदाहरण के लिए कक्षा को एक वस्तु के रूप में त्वरित किया जाता है ।

व्यापक रूप में, एक वर्ग का जीवनचक्र है:

  1. कक्षा के लिए स्रोत कोड एक टेम्पलेट या पैटर्न या स्टैम्प बनाते हुए लिखा जाता है जिसे तब उपयोग किया जा सकता है
  2. newकक्षा का एक वास्तविक वस्तु के रूप में उदाहरण के लिए और फिर जब वस्तु के साथ किया जाता है तो कक्षा का उपयोग करने वाले ऑपरेटर के साथ एक ऑब्जेक्ट बनाएं
  3. कचरा संग्रह के दौरान मेमोरी जैसे संसाधनों को पुनः प्राप्त करने वाली वस्तु को नष्ट करना।

किसी एप्लिकेशन के लिए प्रारंभिक प्रविष्टि बिंदु होने के लिए, जावा ने यह स्वीकार किया है कि जावा प्रोग्राम में एक वर्ग होना चाहिए जिसमें एक सहमति या विशेष नाम के साथ एक विधि शामिल हो। इस विशेष विधि को कहा जाता है main()। चूँकि यह विधि मौजूद होनी चाहिए कि मुख्य विधि से युक्त क्लास को तत्काल किया गया है या नहीं, इस main()पद्धति को staticसंशोधक के साथ घोषित किया जाना चाहिए ताकि जैसे ही कक्षा लोड हो, main()विधि उपलब्ध हो।

इसका परिणाम यह होता है कि जब आप अपने जावा एप्लिकेशन को कमांड लाइन द्वारा शुरू करते हैं जैसे कि java helloworldक्रियाओं की एक श्रृंखला होती है। सबसे पहले एक जावा वर्चुअल मशीन को शुरू और शुरू किया गया है। संकलित जावा कोड युक्त helloworld.class फ़ाइल को जावा वर्चुअल मशीन में लोड किया गया है। तब जावा वर्चुअल मशीन helloworldकक्षा में एक विधि की तलाश करता है जिसे कहा जाता है main(String [] args)। यह विधि staticइतनी होनी चाहिए कि यह तब भी मौजूद रहेगी जब तक कि कक्षा को वास्तव में एक वस्तु के रूप में तत्काल नहीं बनाया गया है। जावा वर्चुअल मशीन कक्षा से एक ऑब्जेक्ट बनाकर कक्षा का एक उदाहरण नहीं बनाता है। यह बस कक्षा को लोड करता है और main()विधि पर निष्पादन शुरू करता है।

इसलिए आपको एक ऑब्जेक्ट के रूप में अपनी कक्षा का एक उदाहरण बनाने की आवश्यकता है और फिर आप उस वर्ग के तरीकों और चर को एक्सेस कर सकते हैं जिन्हें staticसंशोधक के साथ घोषित नहीं किया गया है । एक बार जब आपका जावा प्रोग्राम main()फ़ंक्शन के साथ शुरू हो जाता है तो आप किसी भी चर या विधियों का उपयोग कर सकते हैं जो संशोधक के staticबाद से वे लोड किए जा रहे वर्ग के हिस्से के रूप में मौजूद हैं।

हालाँकि, वर्ग के वे चर और विधियाँ जो उस main()विधि से बाहर हैं जिनके पास staticसंशोधक नहीं है, तब तक उपयोग नहीं किया जा सकता है जब तक कि कक्षा का एक उदाहरण main()विधि के भीतर एक ऑब्जेक्ट के रूप में नहीं बनाया गया हो । ऑब्जेक्ट बनाने के बाद आप तब ऑब्जेक्ट के चर और विधियों का उपयोग कर सकते हैं। वर्ग के उन चर और विधियों का उपयोग करने का प्रयास जिनके पास कक्षा के staticकिसी ऑब्जेक्ट के माध्यम से जाने के बिना संशोधक नहीं है, उन्हें संकलन समय पर जावा कंपाइलर द्वारा पकड़ा गया और एक त्रुटि के रूप में चिह्नित किया गया।

import java.io.*;

class HelloWorld {
    int myInt;      // this is a class variable that is unique to each object
    static int myInt2;  // this is a class variable shared by all objects of this class

    static void main (String [] args) {
        // this is the main entry point for this Java application
        System.out.println ("Hello, World\n");
        myInt2 = 14;    // able to access the static int
        HelloWorld myWorld = new HelloWorld();
        myWorld.myInt = 32;   // able to access non-static through an object
    }
}

11

आइए पहले अपने कार्यक्रम का विश्लेषण करें .. आपके कार्यक्रम में, आपकी पहली विधि है main(), और इसे ध्यान में रखें कि यह स्थैतिक विधि है ... फिर आप उस विधि के लिए स्थानीय चर की घोषणा करते हैं (तुलना, निम्न, उच्च, आदि ..)। इस वैरिएबल का दायरा केवल घोषित विधि है, भले ही यह एक स्थिर या गैर-स्थिर विधि हो। तो आप उस विधि के बाहर उन चर का उपयोग नहीं कर सकते। यह मूल त्रुटि है यू बनाया।

फिर हम अगले बिंदु पर आते हैं। आपने बताया कि स्टेटिक आपको मार रहा है। (यह आपको मार सकता है लेकिन यह केवल आपके कार्यक्रम को जीवन देता है !!) सबसे पहले आपको मूल बात को समझना चाहिए। * स्थैतिक विधि केवल स्थैतिक विधि को बुलाती है और केवल स्थैतिक चर का उपयोग करती है। * स्टेटिक वैरिएबल या स्टैटिक विधि उस वर्ग के किसी भी उदाहरण पर निर्भर नहीं होती है। (यानी यदि आप स्टेटिक वैरिएबल के किसी भी स्टेटस को बदलते हैं तो यह क्लास के सभी ऑब्जेक्ट्स में प्रतिबिंबित होगा) * इस वजह से आप इसे क्लास वेरिएबल या क्लास मेथड के रूप में कहते हैं। और बहुत कुछ "स्थिर" कीवर्ड के बारे में है। मुझे उम्मीद है कि अब आपको यह विचार मिल जाएगा। पहले चर के दायरे को बदलें और इसे एक स्थिर के रूप में घोषित करें (स्थिर तरीकों में इसका उपयोग करने में सक्षम होने के लिए)।

और आपके लिए सलाह यह है: आप वैरिएबल और स्टैटिक फंक्शनलिटी के दायरे के विचार को गलत समझते हैं। उस बारे में स्पष्ट विचार प्राप्त करें।


11

बहुत ही बुनियादी चीज स्थिर चर या स्थिर विधियां हैं जो कक्षा स्तर पर हैं। कक्षा स्तर चर या विधियाँ उदाहरण स्तर के तरीकों या चर से पहले लोड हो जाती हैं। और जाहिर है जो चीज भरी हुई नहीं है उसका उपयोग नहीं किया जा सकता है। इसलिए जावा कंपाइलर रन टाइम में चीजों को संभाले नहीं रखने देता है। इसलिए यह आपको त्रुटि दे रहा है कि गैर-स्थिर चीजों को स्थिर संदर्भ से संदर्भित नहीं किया जा सकता है। बस आपको क्लास लेवल स्कोप, इंस्टेंस लेवल स्कोप और लोकल स्कोप के बारे में पढ़ना होगा।


8

अपने स्थैतिक तरीकों से उन्हें एक्सेस करने में सक्षम होने के लिए उन्हें स्थिर सदस्य चर की आवश्यकता होती है, जैसे:

public class MyProgram7 {
  static Scanner scan = new Scanner(System.in);
  static int compareCount = 0;
  static int low = 0;
  static int high = 0;
  static int mid = 0;  
  static int key = 0;  
  static Scanner temp;  
  static int[]list;  
  static String menu, outputString;  
  static int option = 1;  
  static boolean found = false;

  public static void main (String[]args) throws IOException {
  ...

7

अब आप विधि में इंस्टेंस जोड़ सकते हैं / उपयोग कर सकते हैं

public class Myprogram7 {

  Scanner scan;
  int compareCount = 0;
  int low = 0;
  int high = 0;
  int mid = 0;  
  int key = 0;  
  Scanner temp;  
  int[]list;  
  String menu, outputString;  
  int option = 1;  
  boolean found = false;  

  private void readLine() {

  }

  private void findkey() {

  }

  private void printCount() {

  }
  public static void main(String[] args){

    Myprogram7 myprg=new Myprogram7();
    myprg.readLine();
    myprg.findkey();
    myprg.printCount();
  }
}

बहुत ठोस उदाहरण जो मैंने एक जटिल src फ़ाइल को एक उचित संरचना में संशोधित करने के लिए एक टेम्पलेट के रूप में उपयोग किया था।
XMAN

3

मैं आपको स्थैतिक बात समझाने की कोशिश करूंगा। सबसे पहले सभी स्थिर चर वर्ग के किसी विशेष उदाहरण से संबंधित नहीं हैं। उन्हें वर्ग के नाम से पहचाना जाता है। स्टेटिक तरीके फिर से किसी विशेष उदाहरण से संबंधित नहीं हैं। वे केवल स्थैतिक चर का उपयोग कर सकते हैं। कल्पना कीजिए कि आप MyClass.myMethod () कहते हैं और myMethod एक स्थिर विधि है। यदि आप विधि के अंदर गैर-स्थिर चर का उपयोग करते हैं, तो पृथ्वी पर नरक कैसे पता चलेगा कि किस चर का उपयोग करना है? यही कारण है कि आप स्थैतिक तरीकों से केवल स्थिर चर का उपयोग कर सकते हैं। मैं फिर से दोहराता हूं कि वे किसी विशेष उदाहरण से संबंधित नहीं हैं।


2
  • पहली बात यह है कि किसी वर्ग की आवृत्ति, और स्वयं कक्षा के बीच के अंतर को जानना। एक वर्ग कुछ गुणों को और उन गुणों के संदर्भ में पूरे व्यवहार को दर्शाता है। एक उदाहरण उन गुणों के लिए विशिष्ट मूल्यों को परिभाषित करेगा।

  • स्थैतिक कीवर्ड से जुड़ी कोई भी चीज़ कक्षा के उदाहरण के बजाय कक्षा के संदर्भ में उपलब्ध है

  • उपरोक्त के लिए एक कोरोलरी के रूप में

    1. एक विधि के भीतर चर स्थिर नहीं हो सकते
    2. स्थिर फ़ील्ड और विधियों को वर्ग-नाम जैसे MyProgram7.main (...) का उपयोग करके लागू किया जाना चाहिए
  • एक स्थिर क्षेत्र / विधि का जीवनकाल आपके आवेदन के जीवनकाल के बराबर है

जैसे कहो, कार में संपत्ति का रंग है, और व्यवहार 'गति' को प्रदर्शित करता है। कार का एक उदाहरण 25 किमी प्रति घंटे की गति से रेड वोक्सवैगन बीटल होगा।

अब कार की एक स्थिर संपत्ति सड़क पर पहियों (4) की संख्या होगी, और यह सभी कारों पर लागू होगी।

HTH


1

यह क्लास की फाइलों को लोड करने के लिए जिम्मेदार है। यह तब होता है जब हम अपनी कक्षाओं को लिखते हैं।

उदाहरण 1:

class StaticTest {

      static int a;
      int b;
      int c;
}

अब हम देख सकते हैं कि क्लास "StaticTest" में 3 फ़ील्ड हैं। लेकिन वास्तव में b, c मेंबर वेरिएबल का कोई अस्तित्व नहीं है। लेकिन क्यों ??? ओके लेस्ट की देखिए। यहाँ b, c उदाहरण वेरिएबल हैं। उदाहरण के लिए वेरिएबल को ऑब्जेक्ट निर्माण के समय मेमोरी मिलती है। इसलिए यहाँ b, c को अभी तक कोई मेमोरी नहीं मिल रही है। इसीलिए b, c का कोई अस्तित्व नहीं है। अतः केवल अस्तित्व है। ClassLoader के लिए यह केवल एक के बारे में जानकारी है। ClassLoader अभी तक b, c को नहीं पहचानता है क्योंकि यह अभी तक तात्कालिक नहीं है।

आइए एक और उदाहरण देखें: उदाहरण 2:

class StaticTest {

      public void display() {
          System.out.println("Static Test");
      }


      public static void main(String []cmd) {

             display();       
      }

}

अब यदि हम इस कोड को संकलित करने का प्रयास करते हैं तो CE त्रुटि देगा। CE: गैर-स्थैतिक विधि प्रदर्शन () को स्थिर संदर्भ से संदर्भित नहीं किया जा सकता है।

अब ClassLoader के लिए यह जैसा दिखता है:

class StaticTest {

      public static void main(String []cmd) {

             display();       
      }

}

उदाहरण 2 CE त्रुटि में है क्योंकि हम एक स्थिर संदर्भ से गैर स्थिर विधि कहते हैं। इसलिए क्लासलेडर के लिए कंपाइल टाइम पर मेथड डिस्प्ले () को पहचानना संभव नहीं है। कंपाइल टाइम एरर हो जाता है।


संभवत: दुर्घटना से अपना जवाब प्रस्तुत करने से पहले आप इसे समाप्त करने में कामयाब रहे? कृपया इसे संपादित करें और लापता सामग्री जोड़ें, धन्यवाद!
प्लमट

1

किसी इंस्टेंस मेथड या इंस्टेंस वेरिएबल को कॉल करने से पहले उसे ऑब्जेक्ट (इंस्टेंस) की जरूरत होती है। जब उदाहरण चर स्थिर विधि संकलक से कहा जाता है पता नहीं है कि यह चर किस वस्तु का है। क्योंकि स्थैतिक विधियों में कोई ऑब्जेक्ट नहीं होता (केवल एक प्रति हमेशा)। जब आप इंस्टेंस चर या इंस्टेंस मेथड्स को इंस्टेंस विधि से कहते हैं तो यह thisऑब्जेक्ट को संदर्भित करता है। इसका मतलब है कि चर जो कुछ भी वस्तु से बना है और प्रत्येक वस्तु का उदाहरण विधियों और चर की अपनी प्रतिलिपि है।

स्थैतिक चर के रूप में चिह्नित किया जाता है staticऔर उदाहरण चर में विशिष्ट कीवर्ड नहीं होता है।


0

यह सभी शुरुआती लोगों के लिए स्थिर कुंजी शब्द के बारे में समझाने के लिए थोड़ा अलग है।
जब आप क्लासेस और ऑब्जेक्ट्स के साथ अधिक काम करते हैं तो आपको यह स्पष्ट रूप से पता चल जाता है।

| * | स्टेटिक: स्टेटिक आइटम को क्लास के नाम के साथ बुलाया जा सकता है
यदि आप कोड में निरीक्षण करते हैं, तो कुछ कार्यों को सीधे क्लास के नाम के साथ कहा जाता है

NamCls.NamFnc();

System.out.println();

इसका कारण यह है कि नामफेक और प्रिंटलाइन wil को उनके सामने स्थिर शब्द का उपयोग करते हुए घोषित किया जाना चाहिए।

| * | नॉन स्टैटिक: नॉन स्टैटिक आइटम को क्लास वेरिएबल के साथ बुलाया जा सकता है।
यदि इसकी स्टैटिक नहीं है, तो आपको क्लास के वेरिएबल की जरूरत है,
क्लास के वेरिएबल के बाद डॉट लगाएं और
फिर फंक्शन को कॉल करें।

NamCls NamObjVar = new NamCls();
NamObjVar.NamFnc();


नीचे कोड आपको बड़े करीने से समझाता है

| * | क्लास में स्टेटिक और नॉन स्टेटिक फंक्शन:

public class NamCls
{
    public static void main(String[] args)
    {
        PlsPrnFnc("Tst Txt");

        NamCls NamObjVar = new NamCls();
        NamObjVar.PrnFnc("Tst Txt");
    }

    static void PlsPrnFnc(String SrgPsgVal)
    {
        System.out.println(SrgPsgVal);
    }

    void PrnFnc(String SrgPsgVal)
    {
        System.out.println(SrgPsgVal);
    }
}


| * | एक कक्षा के अंदर स्थैतिक और गैर स्थैतिक कक्षा:

public class NamCls
{
    public static void main(String[] args)
    {
        NamTicCls NamTicVaj = new NamTicCls();
        NamTicVaj.PrnFnc("Tst Txt");

        NamCls NamObjVar = new NamCls();
        NamNicCls NamNicVar = NamObjVar.new NamNicCls();
        NamNicVar.PrnFnc("Tst Txt");
    }

    static class NamTicCls
    {
        void PrnFnc(String SrgPsgVal)
        {
            System.out.println(SrgPsgVal);
        }
    }

    class NamNicCls
    {
        void PrnFnc(String SrgPsgVal)
        {
            System.out.println(SrgPsgVal);
        }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.