在Java中静态方法中调用非静态方法的问题

144

当我尝试在静态类中调用非静态方法时,出现了错误。

无法从类型 playback 中对非静态方法 methodName() 进行静态引用。

我不能将该方法设为静态的,因为这也会导致错误。

该静态方法无法隐藏来自 xInterface 的实例方法。

有没有办法解决在另一个静态方法中调用非静态方法的问题?(这两个方法位于不同的包和不同的类中)。

14个回答

173

从静态方法中调用非静态方法的唯一方法是拥有包含非静态方法的类的实例。 根据定义,非静态方法是在某个类的实例上调用的,而静态方法属于类本身。


110
您可以创建要调用方法的类的实例,例如:
new Foo().nonStaticMethod();

1
@EJP出于安全考虑,这也是我在项目中所做的,在依赖注入的情况下,仅有初始化代码被实例化进行初始化是很有用的,而不是由使用我的API的代码任意决定。因此,当初始化周期发生时,只包含常量和非静态方法的临时对象可以通过依赖注入进行动态初始化,并根据需要安全地加载和丢弃。静态方法的目的更像是函数式编程语言中“纯”函数的目的。 - AMDG

73

首先创建一个类实例,然后使用该实例调用非静态方法。例如,

class demo {

    public static void main(String args[]) {
        demo d = new demo();
        d.add(10,20);     // to call the non-static method
    }

    public void add(int x ,int y) {
        int a = x;
        int b = y;
        int c = a + b;
        System.out.println("addition" + c);
    }
}

14
public class StaticMethod{

    public static void main(String []args)throws Exception{
        methodOne();
    }

    public int methodOne(){
        System.out.println("we are in first methodOne");
        return 1;
    }
}

上述代码未被执行,因为静态方法必须具有该类的引用。

public class StaticMethod{
    public static void main(String []args)throws Exception{

        StaticMethod sm=new StaticMethod();
        sm.methodOne();
    }

    public int methodOne(){
        System.out.println("we are in first methodOne");
        return 1;
    }
}

这一定会被执行。因为我们在这里创建了一个名为"sm"的引用,通过使用该类的引用(即StaticMethod=new Static method()),我们调用了方法一(sm.methodOne())。

我希望这对你有所帮助。


7

您需要一个包含非静态方法的类的实例。

就像当您尝试在没有实例的情况下调用类 String 的非静态方法 startsWith 时:

 String.startsWith("Hello");

您需要的是拥有一个实例并调用非静态方法:
 String greeting = new String("Hello World");
 greeting.startsWith("Hello"); // returns true 

所以您需要创建一个实例来调用它。

7
听起来这个方法确实应该是静态的(即它不访问任何数据成员,也不需要实例才能调用)。由于您使用了“静态类”一词,我理解整个类可能专门用于类似实用程序的静态方法。
然而,Java不允许接口定义的方法为静态。因此,当您(自然地)尝试使方法静态时,会出现“无法隐藏实例方法”的错误。(Java语言规范在第9.4节中提到:“请注意,接口中声明的方法不能声明为静态方法,否则会出现编译时错误,因为静态方法不能是抽象的。”)
因此,只要该方法存在于xInterface中,并且您的类实现了xInterface,就无法将该方法设为静态。
如果您无法更改接口(或不想更改),则有几件事情可以做:
  • 将类设置为单例模式:将构造函数设为私有,并在类中添加一个静态数据成员来保存唯一的实例。这样,您将在实例上调用方法,但至少不会每次需要调用方法时创建新实例。
  • 在您的类中实现2个方法:一个实例方法(如xInterface中定义),和一个静态方法。实例方法将由一行代码组成,委托给静态方法。

非常高级的回答!谢谢! - Hermann Schwarz

4

从静态方法中调用非静态方法的唯一方法是拥有包含非静态方法的类的实例。

class A
{
    void method()
    {
    }
}
class Demo
{
    static void method2()
    {
        A a=new A();

        a.method();
    }
    /*
    void method3()
    {
        A a=new A();
        a.method();
    }
    */

    public static void main(String args[])
    {
        A a=new A();
        /*an instance of the class is created to access non-static method from a static method */
        a.method();

        method2();

        /*method3();it will show error non-static method can not be  accessed from a static method*/
    }
}

谢谢,方法更清晰了,帮了我很多!有时候,声望较低的人也能以这种方式提供帮助。 - Noor Hossain

1
我使用一个接口,并创建一个匿名实例,如下所示:

AppEntryPoint.java

public interface AppEntryPoint
{
    public void entryMethod();
}

Main.java

public class Main
{
    public static AppEntryPoint entryPoint;

    public static void main(String[] args)
    {
        entryPoint = new AppEntryPoint()
        {

            //You now have an environment to run your app from

            @Override
            public void entryMethod()
            {
                //Do something...
                System.out.println("Hello World!");
            }
        }

        entryPoint.entryMethod();
    }

    public static AppEntryPoint getApplicationEntryPoint()
    {
        return entryPoint;
    }
}

这种方法不如创建该类的实例并调用其自身方法那样优雅,但本质上可以实现同样的功能。只是另一种做法。


1

在静态方法或者静态字段中使用非静态方法/字段,或者反过来最简单的方法是...

(为了使这种情况生效,必须至少有一个该类的实例)

这种情况在Android应用程序开发中很常见,例如:一个Activity至少有一个实例。

public class ParentClass{

private static ParentClass mParentInstance = null;

ParentClass(){
  mParentInstance = ParentClass.this;           
}


void instanceMethod1(){
}


static void staticMethod1(){        
    mParentInstance.instanceMethod1();
}


public static class InnerClass{
      void  innerClassMethod1(){
          mParentInstance.staticMethod1();
          mParentInstance.instanceMethod1();
      }
   }
}

注意:这不能像这个建造器方法那样使用.....
String.valueOf(100);

1

有两种方法:

  1. 从静态方法内的实例中调用非静态方法。请参阅法比安(Fabien)的答案,其中包含一个单行示例...尽管我强烈不建议这样做。使用他的示例,他创建了一个类的实例,并仅用于一个方法,然后稍后将其释放。我不建议这样做,因为它将实例视为静态函数。
  2. 将静态方法更改为非静态方法。

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