5

I have a class called GreenhouseControls that has a bunch of

classes built into it such as:

public class ThermostatNight extends Event {
    public ThermostatNight(long delayTime) {
      super(delayTime);
    }
    public void action() {
      // hardware control code here.
      thermostat = "Night";
    }
    public String toString() {
      return "Thermostat on night setting";
    }
  }

I pull values from a text file to get event names such as "ThermostatNight" and time values such as "2000". To instantiate a new object with those values I built a EventFactory that accepts the values as arguments.

This is the class I have built to create new event objects from text file values:

    public class EventFactory{

        public static Event createSpecificEvent(String eventName, long delayTime) {

            Event event = null;

            switch(eventName) {
            case "ThermostatNight": 
                event = new ThermostatNight(delayTime); // Compiler error
                break;
            case "ThermostatDay": 
                event = new ThermostatDay(delayTime);
                break;
            case "LightOn": 
                event = new LightOn(delayTime);
                break;
            case "LightOff": 
                event = new LightOff(delayTime);
                break;
                ...
        }
}

Everything was working well when I ran the program until I pulled the EventFactory class out of GreenhouseControls and into it's own independent class. Now I am getting a compile time error that says:

"No enclosing instance of type GreenhouseControls is accessible. Must qualify the allocation with an enclosing instance of type GreenhouseControls (e.g. x.new A() where x is an instance of GreenhouseControls)."

See in-line comment in EventFactory class to see where the error occurs at "new ThermostatNight(delayTime)"

LooMeenin
  • 818
  • 3
  • 17
  • 33
  • Possible duplicate of [Java - No enclosing instance of type Foo is accessible](http://stackoverflow.com/questions/9560600/java-no-enclosing-instance-of-type-foo-is-accessible) – fabian Mar 03 '16 at 23:18

2 Answers2

5

Your classes are currently inner classes, which need to be constructed in the context of instances of the containing class. Your options are:

  • Specify an instance of the outer class when constructing an instance of the inner class
  • Declare your nested classes as static classes, at which point they won't be inner classes any more
  • Move the nested classes out of the containing class, making them top level classes

Personally I'd go for the last option if possible - nested classes can be useful at times, but you should only use them when there's a real benefit. There are various restrictions which can be quite subtle and which are best avoided if possible. Do you have any compelling reason to make these nested classes?

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
4

The error means that a non-static inner class ThermostatNight is being instantiated from a static method. You need to make the class static (the most likely solution given your code), make the method non-static, or provide an instance explicitly.

public static /*<<==Add this*/ class ThermostatNight extends Event {
    public ThermostatNight(long delayTime) {
      super(delayTime);
    }
    public void action() {
      // hardware control code here.
      thermostat = "Night";
    }
    public String toString() {
      return "Thermostat on night setting";
    }
}

To provide an instance explicitly, use this example:

public static Event createSpecificEvent(GreenhouseControls ctrl, String eventName, long delayTime) {
    Event event = null;
    switch(eventName) {
    case "ThermostatNight": 
        event = ctrl.new ThermostatNight(delayTime);
    ...
}
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • I tried both methods you suggested with success. I like the second method better because I only had to change a few things. Is one better than the other? – LooMeenin Dec 13 '13 at 22:51
  • 1
    @LooMeenin The decision is usually based on the proximity of the inner class to its enclosing class: if `ThermostatNight` needs implicit access to its outer `GreenhouseControls` instance, use the second approach; if it does not need it, use the first approach. – Sergey Kalinichenko Dec 14 '13 at 00:01
  • I have one more question about this program. Was it wise to move the EventFactory class out of the GreenhouseControls in the first place? I am thinking about moving another 3 methods that are related to text file data extraction, out of the GreenhouseControls as well because I may need to keep defining different extraction methods for different types of text files. – LooMeenin Dec 14 '13 at 00:32
  • 1
    @LooMeenin The answer depends mostly on whether or not other classes besides the `GreenhouseControls` need to access the `EventFactory`. If they do, making it a top-level class was probably a good idea; otherwise, keeping it in was probably a better choice. – Sergey Kalinichenko Dec 14 '13 at 01:18