【问题标题】:what is the work-around to "non-static variable cannot be referenced from a static context"? [closed]“不能从静态上下文引用非静态变量”的解决方法是什么? [关闭]
【发布时间】:2013-02-02 13:55:49
【问题描述】:

将方法或匿名内部类以某种方式放入驱动程序类的 main 方法有一个特殊的习惯:

package net.bounceme.dur.misc;

import net.bounceme.dur.misc.Foo;

public class StaticRef {

    Foo f = Foo.INSTANCE;

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

        f.connect();  //move this to inside "run"
        /*
        public void run(){
           StaticRef sf = new StaticRef();
           //do stuff here
        }
         */
    }
}

为了防止出现以下错误:

init:
Deleting: /home/thufir/NetBeansProjects/nntp/build/built-jar.properties
deps-jar:
Updating property file: /home/thufir/NetBeansProjects/nntp/build/built-jar.properties
Compiling 1 source file to /home/thufir/NetBeansProjects/nntp/build/classes
/home/thufir/NetBeansProjects/nntp/src/net/bounceme/dur/misc/StaticRef.java:11: non-static variable f cannot be referenced from a static context
        f.connect();  //move this to inside "run"
1 error
/home/thufir/NetBeansProjects/nntp/nbproject/build-impl.xml:626: The following error occurred while executing this line:
/home/thufir/NetBeansProjects/nntp/nbproject/build-impl.xml:245: Compile failed; see the compiler error output for details.
BUILD FAILED (total time: 0 seconds)

但是,到目前为止我找不到任何东西。我在线程示例中看到了类似的内容,但无法完全理解语法。

以下大部分是我想要的,但我认为它不太正确:

package net.bounceme.dur.misc;

public class StaticRef {

    Foo f = Foo.INSTANCE;

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

        StaticRef sf = new StaticRef();
        sf.f.connect();
    }
}

我想要将 sf 的实例化放入...我不太确定。也许上面是正确的并且“ok”?

【问题讨论】:

  • 在您的示例中, Foo 不是静态的。 f.connect() 将不起作用。您的问题是“我如何在公共静态主体中调用 f.connect()?”。如果是这样,你不能不创建一个 StaticRef 的实例。
  • 对不起,是的,Foo 不是静态的,我也不希望它是静态的。在不声明它是静态或最终的情况下实例化 Foo 的解决方法是什么?我会修改问题,我可能搞混了。
  • @Thufir。在您更新问题之后,我现在真的不明白您想要什么。因为您更新后的代码可以正常工作。
  • Foo f = 前面缺少静态以允许写入sf.f.connect()...
  • 只是引用 Foo 实例有点尴尬,我宁愿它不是静态的也不是最终的,只有私有的。我相信有一个“可运行”使用的习语,我也在 Swing 生成的代码中看到过。

标签: java oop javabeans static-methods idioms


【解决方案1】:

你有一些选择:

  • Foo移动到main的范围内
  • Foo声明为静态变量

    static Foo f = Foo.INSTANCE;
    
  • 创建StaticRef 的实例并使用其中的对象

    new StaticRef().f.connect();
    

【讨论】:

  • 仅用于第二个选项,引用 Foo 对象 f 有点尴尬。
  • 如果它是公共的、受保护的或包可见性,这是​​可能的——但我同意有点尴尬。正确的 OO 样式将表明它使用了一个 getter (getFoo()),但如果它是这样做的,那么......
【解决方案2】:

抱歉,还不能发表评论,所以我必须将其发布为答案。

更新后的代码很好,但由于 Foo.INSTANCE 似乎是对 Singleton pattern 的使用,因此将其定义为静态并像在第一个示例中一样使用它是有意义的。最多只有一个 Foo.INSTANCE 值,因此让每个 StaticRef 实例都有自己对 Foo.INSTANCE 的引用是没有意义的。

【讨论】:

  • 为什么不能到处评论?这只需要 50 声望。
  • 我在 37 分钟前还没有这么“高”的声誉(或者我没有注意到它已被授予)。
【解决方案3】:

您的实例变量无法从静态上下文中引用。 你需要一个类的对象来获取(引用)它的内容。

你可以写一个单例模式:

public class SingletonDemo {
    private static SingletonDemo instance = null;

    private SingletonDemo() {       }

    public static SingletonDemo getInstance() {
            if (instance == null) {
                instance = new SingletonDemo ();
            }
            return instance;
    }

}

如果线程安全是个问题,您可以使用枚举:

public enum Singleton{
    INSTANCE;
    private Singleton(){ ... }
}

public class Singleton{
    private final static Singleton instance = new Singleton();
    private Singleton(){ ... }
    public static Singleton getInstance(){ return instance; }
}

here

【讨论】:

【解决方案4】:

如果此代码“错误”或违反任何 OOP 原则,请发表评论:

package net.bounceme.dur.misc;

public class StaticRef {

    private Foo f = Foo.INSTANCE;

    public StaticRef() throws Exception {
        f.connect();
    }

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

我听说这种方法的理由是,为了重用,只需删除 main 方法,就可以轻松地将 StaticRef 修改为充当 Java Bean。请发表评论。 See also this answer, for a similar solution,或this other answer

【讨论】:

    猜你喜欢
    • 2014-03-18
    • 1970-01-01
    • 2019-03-17
    • 2011-11-30
    • 1970-01-01
    相关资源
    最近更新 更多