Rogue
Rogue

Reputation: 11483

Cannot reference a returned class instance in a static context

I'm attempting to make an object builder that my enum constants can utilize for some simple in-game item management. However, upon using the builder, any returned instance of the class acts as "this" in a literal context, and I cannot utilize it due to the following error:

non-static variable 'this' cannot be referenced from a static context

Why is my code attempting to use an instance of the enum itself when the private class is returning its own instance?

public enum PrisonItem {

    /* Example of an enum constant */
    STUN_STICK(new ItemStackBuilder().setName("&bNightstick").setType(Material.STICK).setAmount(1).build());

    /* Enum instance methods */
    private final ItemStack item;

    private PrisonItem(ItemStack item) {
        this.item = item;
    }

    public ItemStack getItem() {
        return this.item.clone();
    }

    /* Builder for item creation within the enum */
    private class ItemStackBuilder {

        /* Fields representing aspects of the child object */
        protected String name;
        protected List<String> lore = new ArrayList<>();
        protected Map<Enchantment, Integer> enchantments = new HashMap<>();
        protected Material type;
        protected int amount;

        /* Setters */
        public ItemStackBuilder setName(String name) {
            this.name = ChatColor.translateAlternateColorCodes('&', name);
            return this;
        }

        public ItemStackBuilder addLore(String lore) {
            this.lore.add(ChatColor.translateAlternateColorCodes('&', lore));
            return this;
        }

        public ItemStackBuilder addEnchantment(Enchantment ench, int level) {
            this.enchantments.put(ench, level);
            return this;
        }

        public ItemStackBuilder setType(Material type) {
            this.type = type;
            return this;
        }

        public ItemStackBuilder setAmount(int amount) {
            this.amount = amount;
            return this;
        }

        /* Builder */
        public ItemStack build() {
            if (this.type == null || this.amount < 0 || this.amount > 64) {
                throw new IllegalArgumentException("Illegal fields in " + this.getClass().getName() + "!");
            }
            ItemStack back = new ItemStack(this.type);
            back.setAmount(this.amount);
            ItemMeta meta = Bukkit.getItemFactory().getItemMeta(this.type);
            meta.setDisplayName(this.name);
            meta.setLore(this.lore);
            back.setItemMeta(meta);
            back.addEnchantments(this.enchantments);
            return back;
        }

    }

}

However, this seems to work fine when the ItemStackBuilder class is separated and put into its own public class. This seems illogical to me, as the class is only ever used by this enum, and as a nested class it shouldn't act on the enum as a whole I would imagine?

Upvotes: 0

Views: 215

Answers (2)

zubergu
zubergu

Reputation: 3706

Yours ItemStackBuilder is an example of inner class ( class within a class ).

Those kinds of classes can't be instantiated by themselves, they have to be instantiated through object of outer class.

For example:

public class ClassA {
    public class ClassB {
    }
}

You can do:

objA = new ClassA();

but not:

objB = new ClassB();

However:

objA = new ClassA();
objB = objA.new ClassB();

will work like a charm.

More on the subject: http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html or any java book with chapter on inner and nested classes.

Hope it helps.

Upvotes: 0

Brett Okken
Brett Okken

Reputation: 6306

The ItemStackBuilder class is not static. That means any instance must be associated with the parent class. You are attempting to create it from the static initialization of the outer enum class, which I believe is what is causing your problem. Change ItemStackBuilder to be static and your issue should go away.

Upvotes: 2

Related Questions