非静态方法无法从静态上下文中引用

21

首先是一些代码:

import java.util.*;
//...

class TicTacToe 
{
//...

public static void main (String[]arg) 
{ 

    Random Random = new Random() ; 
    toerunner () ; // this leads to a path of 
                   // methods that eventualy gets us to the rest of the code 
} 
//... 

public void CompTurn (int type, boolean debug) 
{ 
//...

        boolean done = true ; 
        int a = 0 ; 
        while (!done) 
        { 
            a = Random.nextInt(10) ;
            if (debug) { int i = 0 ; while (i<20) { System.out.print (a+", ") ; i++; }} 
            if (possibles[a]==1) done = true ; 
        } 
        this.board[a] = 2 ; 


}
//...

} //to close the class 

以下是错误信息:

TicTacToe.java:85: non-static method nextInt(int) cannot be referenced from a static context
            a = Random.nextInt(10) ;
                      ^

到底出了什么问题?那个错误信息“非静态方法无法从静态上下文中引用”是什么意思?


2
"Random Random = new Random()" 应该改为 "Random random = new Random()"。 - JRL
请参见http://stackoverflow.com/questions/2694470/whats-wrong-with-my-random。 - Mark Elliot
4个回答

36

你正在使用 Random.nextInt 的静态调用方式。

相反,应该先创建一个变量 Random r = new Random();,然后调用 r.nextInt(10)

一定要看一下这个链接:

更新:

你真的应该替换这行代码,

Random Random = new Random(); 

使用类似这样的东西:

Random r = new Random();
如果你将变量名用作类名,你会遇到一大堆问题。此外,作为 Java 的惯例,使用小写字母命名变量。这可能有助于避免一些混淆。

我不相信这是真的,一旦main运行,它会调用toerunner执行任何操作,因此toerunner将不知道随机实例。 - Anthony Forloney
@David 你的主方法声明了r作为局部变量,因此它无法从CompTurn()实例方法中访问。在这种情况下,我建议你将r声明为一个静态类字段,例如 private static final Random r = new Random(); - Kevin K
1
是的,它是一个对象,但它的作用域仅限于主函数,因此在其他方法中不可见。 - OscarRyz
当我这样做的时候(通过使用对象调用方法),我会得到一个空指针异常。你认为问题是什么?如果需要代码,请告诉我。谢谢!(我已经被卡了三个半小时了!) - Ruchir Baronia
@RuchirBaronia 如果我们不知道您使用的代码,我们就无法为您提供准确的答案。我建议您在此网站上搜索其他类似的问题,看看是否可以自己找到答案;否则,我建议您打开一个新问题,并提供代码和您尝试过的详细信息。 - Anthony Forloney
显示剩余6条评论

3
在Java中,静态方法属于类而不归实例所有。这意味着你不能从静态方法中调用其他实例方法,除非它们在你已经在该方法中初始化的实例中被调用。
以下是您可能想要执行的操作:
public class Foo
{
  public void fee()
  {
     //do stuff  
  }

  public static void main (String[]arg) 
  { 
     Foo foo = new Foo();
     foo.fee();
  } 
}

请注意,您正在从已实例化的实例中运行实例方法。您不能直接从静态方法调用类实例方法,因为该静态方法没有与其相关联的实例。

2

您正在尝试在类本身上调用一个实例方法。

您应该这样做:

    Random rand = new Random();
    int a = 0 ; 
    while (!done) { 
        int a = rand.nextInt(10) ; 
    ....

与其像我之前在这里所说的那样stackoverflow.com/questions/2694470/whats-wrong...


如果我把第一行放在主函数里,它还能正常工作吗?(请参考我对安东尼答案的评论)。 - David
在 mane 中?你是指 main 吗?不,main 中声明的随机数只在该方法中有效。一旦进入第二个方法,它就无法访问。 - OscarRyz
当我调用这个方法时,我遇到了空指针异常...您认为问题是什么?如果需要任何代码,请告诉我。谢谢!(我已经卡在这里3个半小时了!) - Ruchir Baronia
@RuchirBaronia,请提出您的问题并发布您的代码,应该很容易解决。 - OscarRyz

0

违反Java命名约定(变量名和方法名以小写字母开头,类名以大写字母开头)会导致混淆。

变量Random仅在main方法内部“在范围内”。它对于任何由main调用的方法都不可访问。当您从main返回时,变量消失了(它是堆栈帧的一部分)。

如果您希望类的所有方法使用相同的Random实例,请声明一个成员变量:

class MyObj {
  private final Random random = new Random();
  public void compTurn() {
    while (true) {
      int a = random.nextInt(10);
      if (possibles[a] == 1) 
        break;
    }
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接