java cannot make a static reference to the non-static method

Posted in :

我最後,還是無法理解和運用static, 這似乎太難.


I am not able to understand what is wrong with my code.

class Two {
    public static void main(String[] args) {
        int x = 0;

        System.out.println("x = " + x);
        x = fxn(x);
        System.out.println("x = " + x);
    }

    int fxn(int y) {
        y = 5;
        return y;
    }
}

Exception in thread “main” java.lang.Error: Unresolved compilation problem: Cannot make a static reference to the non-static method fxn(int) from the type Two


Since the main method is static and the fxn() method is not, you can’t call the method without first creating a Two object. So either you change the method to:

public static int fxn(int y) {
    y = 5;
    return y;
}

or change the code in main to:

Two two = new Two();
x = two.fxn(x);

Read more on static here in the Java Tutorials.


static這關鍵字能使用在inner class/method/variable,什麼時候會需要static的variable?

當該變數屬於某一class時,而不是屬於某一instance時,就會使用static variable。無論在任何instance中,存取的static variable都是相同的,或是說該static variable在memory中只有一份,存取時都是取該memory的資料。
當定一method為static時,代表該method屬於class,就是說不需要instance就能使用該method,當然就沒有new的動作,大部分的utility methods都是定為static的。如果在static method使用non-static variable時,會發生compile error。static method在instance尚未建立前就能使用(call),那non-static variable都沒生成,這樣static method要怎麼用?
下面的程式會發生錯誤,錯誤訊息為”Cannot make a static reference to the non-static field var”。

1
2
3
4
5
6
7
8
9
public class InvokeNonStaticVariable {
 
    private int var = 1;
   
    public static void main(String[] args) {
        System.out.println(var);
    }
    
}

static variable在class loading時就建立,而instance variable(InvokeNonStaticVariable中的var)在new的時候才會建立。
static method是無法覆寫的,因為它是屬於class的,從下面的程式碼來說明。定義時就是定義為class A,即使用new B( ),但前面提到static member是屬於class的,與生成的instance無關。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class A {
 
    public static void printName() {
        System.out.println("A");
    }
     
    public void printNumb() {
        System.out.println("65");
    }
}
 
public class B extends A {
 
    public static void printName() {
        System.out.println("B");
    }
    public void printNumb() {
        System.out.println("66");
    }
}
 
public class StaticMethodOverrideExample {
     
    public static void main(String[] args) {
        A a = new B();   
        B b = new B();
        a.printName();
        a.printNumb();
        b.printName();
        b.printNumb();
    }
}

執行後的結果為

1
2
3
4
A
66
B
66

static method不能override的部份是指在printName中,a.printName()輸出的依然是A,但是在a.printNumb()輸出的卻是class B中設定的66。另外如果是eclipse,會建議使用者將程式修改為直接call static method,如下。

1
2
3
4
5
6
7
8
9
10
11
public class FixStaticMethodOverrideExample {
 
    public static void main(String[] args) {
        A a = new B();
        B b = new B();
        A.printName();
        a.printNumb();
        B.printName();
        b.printNumb();
    }
}

相關來源
http://javarevisited.blogspot.com/2011/11/static-keyword-method-variable-java.html


我在一个类中写了一个public void getDate()方法和一个main方法,在main方法中直接调用getDate()方法,于是就出现了这个错误提示。后来实例化类,再用实例化的类调用getDate()方法就没问题了。

在静态方法中,不能直接访问非静态成员(包括方法和变量)。

因为,非静态的变量是依赖于对象存在的,对象必须实例化之后,它的变量才会在内存中存在。例如一个类 Student 表示学生,它有一个变量 String address。如果这个类没有被实例化,则它的 address 变量也就不存在。而非静态方法需要访问非静态变量,所以对非静态方法的访问也是针对某一个具体的对象的方法进行的。对它的访问一般通过 objectName.methodName(args……) 的方式进行。

而静态成员不依赖于对象存在,即使是类所属的对象不存在,也可以被访问,它对整个进程而言是全局的。因此,在静态方法内部是不可以直接访问非静态成员的。

Static methods cannot call non-static methods. An instance of the class is required to call its methods and static methods are not accociated with an instance (they are class methods). To fix it you have a few choices depending on your exact needs.

/**
*  Will not compile
*/

public class StaticReferenceToNonStatic
{
   public static void myMethod()
   {
      // Cannot make a static reference
      // to the non-static method
      myNonStaticMethod();
   }

   public void myNonStaticMethod()
   {
   }
}

/**
* you can make your method non-static
*/

public class MyClass
{
   public void myMethod()
   {
      myNonStaticMethod();
   }

   public void myNonStaticMethod()
   {
   }
}

/**
*  you can provide an instance of the
*  class to your static method for it
*  to access methods from
*/

public class MyClass
{
   public static void myStaticMethod(MyClass o)
   {
      o.myNonStaticMethod();
   }

   public void myNonStaticMethod()
   {
   }
}

/**
*  you can make the method static
*/

public class MyClass
{
   public static void myMethod()
   {
      f();
   }

   public static void f()
   {
   }
}

报错原因:

在一个类中写了一个public String getContent()方法和一个main()方法,getContent()方法中包含了getClass()方法,在main()方法中直接调用了getContent()就出现如题的错误。这样一样

解决方法:

先实例化类,然后再调用getContent()就没有问题了

  1. GetProperties gp = new GetProperties();
  2. String s = gp.getCotent();

说明:

在静态方法中,不能直接访问非静态成员(包括方法和变量)。因为,非静态的变量是依赖于对象存在的,对象必须实例化之后,它的变量才会在内存中存在。例如一个类 Student 表示学生,它有一个变量String address。如果这个类没有被实例化,则它的 address 变量也就不存在。而非静态方法需要访问非静态变量,所以对非静态方法的访问也是针对某一个具体的对象的方法进行的。对它的访问一般通过 objectName.methodName(args……) 的方式进行。而静态成员不依赖于对象存在,即使是类所属的对象不存在,也可以被访问,它对整个进程而言是全局的。因此,在静态方法内部是不可以直接访问非静态成员的。

Source Code如下:

  1. import java.io.FileNotFoundException;
  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.util.Properties;
  5. public class GetProperties {//不用static
  6. public String getCotent(){//不用static
  7. String content=””;
  8. try {
  9. Properties properties = new Properties();
  10. InputStream is = getClass().getResourceAsStream(“test.properties”);//ok
  11. //InputStream is = getClass().getClassLoader().getResourceAsStream(“test.properties”); //ERROR:Exception in thread “main” java.lang.NullPointerException
  12. properties.load(is);
  13. is.close();
  14. content = properties.getProperty(“str1″);
  15. catch (FileNotFoundException ex) {
  16. ex.printStackTrace();
  17. }catch (IOException ex) {
  18. ex.printStackTrace();
  19. }
  20. return content;
  21. }
  22. public static void main(String[] args){
  23. GetProperties gp = new GetProperties();//实例化
  24. String s = gp.getCotent();
  25. System.out.println(s);
  26. }
  27. }
  28. test.properties中内容为str1=123

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *