Christian Benincasa
Christian Benincasa

Reputation: 1215

Non-static variable referenced in static context error with interface

I am fairly new to Java (especially interfaces) and I have this simple comparison interface set up and am wishing to create an integer implementation for it. When I compile, the compiler returns an error stating that I cannot reference this non-static variable in a static context. I understand this error...but I am not sure why it is happening in this context.

The initialization looks correct according to examples I've seen. Perhaps I just need another set of eyes to look at this code and see what I am missing.

I appreciate any help.

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;
        }
    }
}

The offending line:

    Icmp cmp = new Icmp();

The error:

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

Upvotes: 0

Views: 2497

Answers (3)

alf
alf

Reputation: 8523

Well, now it is better. The point is, neither interface nor class are static—they can only be created using an instance of Test, try

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

Alternatively, you may consider making inner class and interface static:

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;
        }
    }
}

Yet another option is to get rid of inner classes/interfaces:

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();
    }
}

As you can see, all solutions are similar—that's why the actual code was vital for getting a reasonable answer.

Following up on comments: inner class (literally, a class within another class) means that this class is a part of enclosing object. Or, if it is static—a part of enclosing class. The important thing about non-static inner classes is that they can access members (fields, methods, including private ones) of an enclosing object; hence the tricky syntax.

In order for the inner class object to be able to do that, it stores an implicit reference to the enclosing object.

With interfaces, as @Voo rightfully say, you never access anything, and never have any references—inner interfaces are always static.

For further reading, take Kathy Sierra's books. Or JLS if you prefer hardcore specs.

Upvotes: 2

David Harkness
David Harkness

Reputation: 36562

Because Icmp doesn't actually use an enclosing Test instance, it would be better to either make it a static class of Test, assuming you really want to keep it inside Test.

static class Icmp implements Cmp { ... }

Upvotes: 0

Stephen P
Stephen P

Reputation: 14830

There are three separate pieces here: the Interface Cmp, the Implementation Icmp, and the user of the implementation LabFour.java.

What files are these in? You should have three files: Cmp.java, Icmp.java, and LabFour.java You can have only two files if you have a test main() method within Icmp.java

The class Icmp should probably be public.

You need to show more of what's in LabFour.java to show what context your "offending line" is in.


Edit.

In your new Test example, the error is happening because it's all defined in one file.

The class Icomp is an inner class of the class Test, and an inner class needs an instance of the containing class to work.

You need to create an enclosing instance of your Test class. Change your main to this:

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'
}

This would also work if Test, Cmp, and Icmp were, as I already mentioned, defined in three separate files.

Upvotes: 0

Related Questions