0

I am having trouble instantiating a class using Class.forName(). At first, I was trying to create the class by using just the class name but it kept on throwing "ClassNotFoundError". So, I added the package name but the format for me is package$className. E.g:

`Class<?> cls = Class.forName("GreenhouseControls$ThermostatNight"); //` This Works.

I read class names that need to be instantiated from a file. Once the class created, I add the event using the addEvent() function from the controller class.

Unfortunately, when I try to get the constructor to instantiate the class, I get a "NoSuchMethodError". I am not sure why? I am wondering if it's the abstract class that is not allowing me to get the subclass constructor?

GreenhouseControls.java

import java.io.*;
import java.lang.reflect.*;
import java.lang.Long;
import java.util.*;
import java.util.regex.*;
import tme3.*;

public class GreenhouseControls extends Controller{


    public class ThermostatNight extends Event {

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



   public class Restart extends Event {
     public Restart(long delayTime, String filename) {
       super(delayTime);
       eventsFile = filename;
     }

     public void action()  {
       File f = new File(eventsFile);
       try{
         Scanner scan = new Scanner(f);
         Pattern class_name = Pattern.compile("(?<==)(.*)(?=,time)");
         Pattern time1 = Pattern.compile("(?<=time=)(.*)(?=,*)");
         Pattern rings_time = Pattern.compile("(?<=time=)(.*)(?=,)");
         Pattern rings = Pattern.compile("(?<=rings=)(.*)");



         while(scan.hasNextLine()){
            String event_name;
            long l;
            int r = 0;
            Class<?> cls;
            Constructor<?> clsCon;
            event_name = scan.findInLine(class_name)

            try{ 
               String check = scan.findInLine(rings_time);
               check.getClass();
               l = Long.valueOf(check).longValue();
               r = Integer.valueOf(scan.findInLine(rings)).intValue();

            }catch(NullPointerException e){ l = Long.valueOf(scan.findInLine(time1)).longValue(); }

            System.out.println("event_name: " + event_name + " Time: " + l + " Rings: " + r);

           cls = Class.forName("GreenhouseControls$ThermostatNight");

           clsCon = cls.getDeclaredConstructor(); // This Code throws and error because apparently there is no constructor

           if (scan.hasNextLine())
                scan.nextLine();     


         }
      }catch(Exception e) { System.out.println(e); }
    //addEvent(new ThermostatNight(0));
   }   
  }




    public static void main(String[] args) {
      try {
        String option = args[0];
        String filename = args[1];

        if ( !(option.equals("-f")) && !(option.equals("-d")) ) {
          System.out.println("Invalid option");
          printUsage();
        }

        GreenhouseControls gc = new GreenhouseControls();

        if (option.equals("-f"))  {
          gc.addEvent(gc.new Restart(0,filename));
        }

        gc.run();
      }
      catch (ArrayIndexOutOfBoundsException e) {
         System.out.println("Invalid number of parameters");
         printUsage();
      }
   }    
}

Event.java

package tme3;

import java.io.*;

public abstract class Event {
  private long eventTime;
  protected final long delayTime;

  public Event(){ delayTime = 0;}
  public Event(long delayTime) {
    this.delayTime = delayTime;
    start();
  }
 public void start() { // Allows restarting
   eventTime = System.currentTimeMillis() + delayTime;
 }
 public boolean ready() {
  return System.currentTimeMillis() >= eventTime;
 }
 public abstract void action();
 }  
}

Controller.java

public class Controller {
    // A class from java.util to hold Event objects:
    private List<Event> eventList = new ArrayList<Event>();
    public void addEvent(Event c) { eventList.add(c); }

    public void run() {
        while(eventList.size() > 0)
            // Make a copy so you're not modifying the list
            // while you're selecting the elements in it:
        for(Event e : new ArrayList<Event>(eventList))
            if(e.ready()) {
            System.out.println(e);
            e.action();
            eventList.remove(e);
        }
    }
}
Woody008
  • 96
  • 1
  • 2
  • 9
  • ThermostatNight is an instance inner class of GreenhouseControls, in order to create an instance of it, you will need an instance of the outer class, GreenhouseControls – MadProgrammer Dec 11 '15 at 21:14
  • Post minimal code required to reproduce your problem. Also since `ThermostatNight` is inner class you need outer class instance to instantiate it. – Pshemo Dec 11 '15 at 21:14
  • 2
    It's unclear why you're using a non-static inner class, and why you would need reflection in the first place. It's also a very bad practice to put your classes in the default package. What do you want to achieve? What's the goal of using reflection here? – JB Nizet Dec 11 '15 at 21:16
  • Well this is an assignment I did not built this the only part that is my code is the void action within the Class Restart. So I have a file that contains some class names such ThermostatNight with a delaytime number so I have to read each line and create the event. – Woody008 Dec 11 '15 at 21:23

2 Answers2

1

You cannot directly create an inner class like you are attempting to do. You can only create object of type GreenhouseControls.

JJF
  • 2,681
  • 2
  • 18
  • 31
0

You have to pass Long.TYPE to getDeclaredConstructor so that it looks for ThermostatNight(long). Currently it's looking for a declared constructor called ThermostatNight().

cls = Class.forName("GreenhouseControls$ThermostatNight");
clsCon = cls.getDeclaredConstructor(Long.TYPE);
Kyle Sletten
  • 5,365
  • 2
  • 26
  • 39
  • Your idea is correct, but won't work for two reasons, 1: Long.class is not the same as long.class; 2: You need an instance of the outer class before you can create an instance of the inner class – MadProgrammer Dec 11 '15 at 21:17
  • Well, if you noticed, I used `Long.TYPE` (same thing as `long.class`) not `Long.class`. As for the inner class thing, yeah, that's true. – Kyle Sletten Dec 11 '15 at 21:19
  • Sorry I forgot to add the Long.Type in my code but i am still getting java.lang.NoSuchMethodException: GreenhouseControls$ThermostatNight.(long) – Woody008 Dec 11 '15 at 21:19
  • Sorry, on the phone, so I only saw Long., my bad – MadProgrammer Dec 11 '15 at 21:28