具有接口的静态上下文错误中引用的非静态变量

时间:2011-10-20 23:42:21

标签: java interface

我是Java的新手(尤其是接口),我已经设置了这个简单的比较接口,并且希望为它创建一个整数实现。编译时,编译器返回一个错误,指出我无法在静态上下文中引用此非静态变量。我理解这个错误......但我不确定为什么会发生这种情况。

根据我见过的例子,初始化看起来是正确的。也许我只需要另一组眼睛来查看这段代码,看看我错过了什么。

我感谢任何帮助。

public class Test
{
    public static void main(String[] args)
    {
        Icmp test = new Icmp();
    }

    public interface Cmp
    {
        public int cmp(Object x, Object y);
    }

    class Icmp implements Cmp
    {
        public int cmp(Object o1, Object o2)
        {
            int i1 = ((Integer) o1).intValue();
            int i2 = ((Integer) o2).intValue();

            if(i1<i2)
                return -1;
            else if(i1==i2)
                return 0;
            else
                return 1;
        }
    }
}

违规行:

    Icmp cmp = new Icmp();

错误:

LabFour.java:20: non-static variable this cannot be referenced from a static context
        Icmp cmp = new Icmp();
                   ^

3 个答案:

答案 0 :(得分:2)

嗯,现在好多了。关键是,接口和类都不是静态的 - 它们只能使用Test的实例创建,请尝试

Icmp test = (new Test()).new Icmp()

或者,您可以考虑使内部类和接口静态:

public class Test {
    public static void main(String[] args) {
        Icmp test = new Icmp();
    }

    public static interface Cmp {
        public int cmp(Object x, Object y);
    }

    static class Icmp implements Cmp {
        public int cmp(Object o1, Object o2) {
            int i1 = ((Integer) o1).intValue();
            int i2 = ((Integer) o2).intValue();

            if (i1 < i2)
                return -1;
            else if (i1 == i2)
                return 0;
            else
                return 1;
        }
    }
}

另一种选择是摆脱内部类/接口:

interface Cmp {
    public int cmp(Object x, Object y);
}

class Icmp implements Cmp {
    public int cmp(Object o1, Object o2) {
        int i1 = ((Integer) o1).intValue();
        int i2 = ((Integer) o2).intValue();

        if (i1 < i2)
            return -1;
        else if (i1 == i2)
            return 0;
        else
            return 1;
    }
}

public class Test {
    public static void main(String[] args) {
        Icmp test = new Icmp();
    }
}

正如您所看到的,所有解决方案都相似 - 这就是为什么实际代码对于获得合理答案至关重要。

跟随注释:内部类(字面意思是另一个类中的类)意味着该类是封闭对象的一部分。或者,如果它是静态的 - 封闭类的一部分。非静态内部类的重要之处在于它们可以访问封闭对象的成员(字段,方法,包括私有内容);因此棘手的语法。

为了使内部类对象能够这样做,它存储对封闭对象的隐式引用。

使用接口,正如@Voo正确地说,你永远不会访问任何东西,并且永远不会有任何引用 - 内部接口总是静态的。

如需进一步阅读,请参阅Kathy Sierra的书籍。或者JLS,如果您更喜欢硬核规格。

答案 1 :(得分:0)

此处有三个单独的部分:界面Cmp,实施Icmp和实施用户LabFour.java

这些文件是什么?您应该有三个文件:Cmp.javaIcmp.javaLabFour.java 如果main()

中有测试Icmp.java方法,则只能有两个文件

班级Icmp应该是公开的。

您需要在LabFour.java中显示更多内容,以显示您的“违规行”所处的背景。


编辑。

在新的Test示例中,错误发生在,因为它都在一个文件中定义。

Icomp是类Test内部类,内部类需要包含类的实例才能工作。

您需要创建Test类的封闭实例。将您的主要内容更改为:

public static void main(String[] args)
{
    Test t = new Test(); // enclosing instance of Test
    Icmp test = t.new Icmp(); // create an Icmp in the context of 't'
}

如果我已经提到过,Test,Cmp和Icmp在三个单独的文件中定义,这也会有效。

答案 2 :(得分:0)

因为Icmp实际上并没有使用封闭的Test实例,所以最好让它成为Test的静态类,假设你真的希望将其保留在Test内。

static class Icmp implements Cmp { ... }