2010-04-01 83 views
192

我寫這個測試代碼中引用:非靜態變量不能從靜態上下文

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); 
         ^

我如何得到我的方法識別我的類變量?

+0

這可能幫助 - http://www.buggybread.com/2014/06/error-cannot-use-this-in-static-context.html – 2014-08-25 21:04:04

+0

嘗試儘可能避免使用靜態。你可以編寫一個完整的程序,全部是靜態的,就像'C'一樣。但它不會是一個很好的。嘗試按照它所使用的方式使用Java,作爲面向對象的語言。 – 2015-09-15 16:21:57

回答

7

爲了能夠從您的靜態方法來訪問他們所需要的是靜態成員變量,就像這樣:

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 { 
    ... 
196

你必須明白一個類和類的實例之間的差別。如果您在街上看到一輛汽車,即使您無法看清哪種車型或類型,您也會立即知道它是一輛汽車。這是因爲你比較你所看到的「汽車」。該課程包含與所有汽車類似的課程。把它看作一個模板或一個想法。

與此同時,您看到的汽車是「汽車」類的一個實例,因爲它具有您期望的所有特性:有人駕駛它,它有一個引擎,車輪。

所以班級說「所有的車都有顏色」,實例說「這輛車是紅色的」。

在OO世界中,您定義了類並在類中定義了一個類型爲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())。

+0

我現在正在向我們的新同事解釋這一點 - 感謝這個偉大的解釋。這應該是可以接受的答案。 – Supahupe 2018-01-09 13:45:52

4

我會盡力向你解釋靜態的東西。首先,靜態變量不屬於該類的任何特定實例。他們被承認與班級的名字。靜態方法再次不屬於任何特定的實例。他們只能訪問靜態變量。想象一下你調用MyClass.myMethod(),myMethod是一個靜態方法。如果你在方法內使用非靜態變量,地球上的地獄它會知道使用哪些變量?這就是爲什麼你可以只使用靜態方法的靜態變量。我再說一遍,他們不屬於任何特定的情況。

49

靜態字段和方法連接到類本身,而不是它的實例。如果您有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 
    } 
} 
2
  • 的第一件事情就是要知道一個類的實例,類本身之間的差異。一個類對某些屬性進行建模,並對這些屬性的上下文中的整體行爲進行建模。一個實例將爲這些屬性定義特定的值。

  • 任何結合到靜態關鍵字可用在類的上下文中而不是在類

  • 的一個實例的上述

    上下文作爲推論內的
    1. 變量方法不能是靜態的,必須使用類名稱調用方法,例如MyProgram7.main(...)
  • 靜態字段的壽命/方法等同於您的應用程序

例如壽命說,汽車有屬性的顏色,並展示行爲'運動'。 這輛車的一個實例是一輛紅色大衆甲殼蟲,時速25公里。

現在汽車的靜態屬性是道路上的車輪(4)的數量,並且這將適用於所有汽車。

HTH

11

讓我們來分析你的程序首先.. 在你的程序中,你的第一個方法是main(),並牢記它是靜態的方法...然後你聲明的局部變量對於該方法( compareCount,low,high等)。這個變量的範圍只是聲明的方法,不管它是靜態方法還是非靜態方法。所以你不能在這個方法之外使用這些變量。這是你所犯的基本錯誤。

然後我們來到下一點。你告訴靜態正在殺死你。 (它可能會殺死你,但它只會給你的程序帶來生命!!)首先你必須理解基本的東西。 *靜態方法僅調用靜態方法並僅使用靜態變量。 *靜態變量或靜態方法不依賴於該類的任何實例。 (即,如果更改靜態變量的任何狀態,它將反映在該類的所有對象中) *因此,可以將其稱爲類變量或類方法。 還有更多關於「靜態」關鍵字的內容。 我希望現在你明白了。首先更改變量的範圍並將其聲明爲靜態(以便能夠在靜態方法中使用它)。

而你的建議是:你誤解了變量和靜態功能範圍的想法。得到清楚的想法。

9

非常基本的事情是靜態變量或靜態方法在課堂上。類級別的變量或方法在實例級方法或變量之前加載。顯然,未加載的內容不能使用。所以java編譯器不會讓運行時處理的東西在編譯時解決。這就是爲什麼它給你錯誤非靜態的東西不能從靜態上下文中引用。您只需要閱讀關於類級範圍,實例級範圍和本地範圍。

6

現在可以在所述方法中

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(); 
    } 
} 
24

static關鍵字修改類內的方法或可變的生命週期加/使用與實例。一個static方法或變量是在加載類時創建的。只有在例如通過使用new運算符將類實例化爲對象時,纔會創建未聲明爲static的方法或變量。

一類的生命週期,在廣義上講,是:

  1. 爲類的源代碼被寫入創建隨後可以用來
  2. 創建對象的模板或 圖案或印模new運算符使用該類將該類的實例作爲實際對象,然後在完成該對象後,銷燬垃圾收集期間回收其所持有的資源(如內存)的對象。

爲了讓應用程序具有初始入口點,Java採用了約定,即Java程序必須包含一個包含具有約定名稱或特殊名稱的方法的類。這種特殊的方法被稱爲main()。由於無論包含main方法的類是否已實例化,該方法都必須存在,因此必須使用static修飾符聲明main()方法,以便在加載該類時立即可用main()方法。

結果是,當您通過命令行(如java helloworld)啓動Java應用程序時,會發生一系列操作。首先啓動並初始化Java虛擬機。接下來將包含已編譯的Java代碼的helloworld.class文件加載到Java虛擬機中。然後,Java虛擬機在helloworld類中尋找名爲main(String [] args)的方法。此方法必須爲static,以便即使該類未實際實例化爲對象,它也會存在。 Java虛擬機不通過從類創建對象來創建類的實例。它只是加載類並開始執行main()方法。

因此,您需要創建一個類的實例作爲對象,然後您可以訪問未使用static修飾符聲明的類的方法和變量。一旦你的Java程序啓動了main()函數,你就可以使用修飾符爲static的任何變量或方法,因爲它們是被加載的類的一部分。

但是,在main()方法之外,沒有static修飾符的類中的那些變量和方法只有在該類的實例已被創建爲main()方法中的對象之後才能使用。創建對象後,可以使用對象的變量和方法。Java編譯器在編譯時會捕獲未使用類的對象而使用沒有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 
    } 
} 
0

它是ClassLoader負責加載類文件。讓我們看看當我們寫我們自己的類時會發生什麼。

實施例1:

class StaticTest { 

     static int a; 
     int b; 
     int c; 
} 

現在,我們可以看出,類 「StaticTest」 具有3 fields.But實際上沒有存在B的,C構件variable.But爲什麼???。好吧,看看。這裏b,c是實例變量。因爲實例變量在創建對象時獲取內存。所以這裏b,c還沒有獲得任何記憶。這就是爲什麼不存在b,c。所以只存在一個。 對於ClassLoader,它只有一個關於a的信息。 ClassLoader尚未識別b,c,因爲它的對象尚未實例化。

讓我們來看看另一個例子: 例2:

class StaticTest { 

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


     public static void main(String []cmd) { 

      display();  
     } 

} 

現在,如果我們試圖編譯這段代碼編譯器會給出錯誤的CE。 CE:非靜態方法display()不能從靜態上下文中引用。

現在對於類加載器,它看起來像:

class StaticTest { 

     public static void main(String []cmd) { 

      display();  
     } 

} 

在例2 CE錯誤是因爲我們所說的從靜態上下文非靜態方法。所以ClassLoader在編譯時不能識別方法display(),所以編譯時發生錯誤。

+0

可能在您完成之前,意外地提交了您的答案?請修改並添加缺少的內容,謝謝! – plamut 2015-09-03 12:27:38

1

這是比較差異來解釋所有初學者的靜態關鍵詞。
當您更多地使用類和對象時,您將清楚地瞭解它。

| * | 靜態:靜態項目可以與類名被稱爲
如果你在代碼觀察,一些功能被直接調用類的名字,如

NamCls.NamFnc(); 

System.out.println(); 

這是因爲NamFnc和println西港島線使用前關鍵字靜態聲明他們。

| * | 非靜態:非靜態的物品可以用類變量
如果它不是靜態調用,您需要的類的變量,類變量後
投放點和
然後調用函數。

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); 
     } 
    } 
} 
相關問題