Не може да се създаде клас с помощта на Class.forName()

Имам проблем с инстанцирането на клас с помощта на Class.forName(). Отначало се опитвах да създам класа, като използвах само името на класа, но той продължаваше да извежда „ClassNotFoundError“. И така, добавих името на пакета, но форматът за мен е package$className. например:

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

Чета имена на класове, които трябва да бъдат инстанцирани от файл. След като класът е създаден, добавям събитието с помощта на функцията addEvent() от класа на контролера.

За съжаление, когато се опитвам да накарам конструктора да инстанцира класа, получавам „NoSuchMethodError“. Не съм сигурен защо? Чудя се дали това е абстрактният клас, който не ми позволява да получа конструктора на подклас?

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

Контролер.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);
        }
    }
}

person Woody008    schedule 11.12.2015    source източник
comment
ThermostatNight е вътрешен клас на екземпляр на GreenhouseControls, за да създадете негов екземпляр, ще ви трябва екземпляр на външния клас, GreenhouseControls   -  person MadProgrammer    schedule 12.12.2015
comment
Публикувайте минимален код, необходим за възпроизвеждане на вашия проблем. Освен това, тъй като ThermostatNight е вътрешен клас, имате нужда от екземпляр на външен клас, за да го инстанциирате.   -  person Pshemo    schedule 12.12.2015
comment
Не е ясно защо използвате нестатичен вътрешен клас и защо на първо място ще имате нужда от отражение. Също така е много лоша практика да поставяте вашите класове в пакета по подразбиране. какво искаш да постигнеш Каква е целта на използването на отражение тук?   -  person JB Nizet    schedule 12.12.2015
comment
Ами това е задание, което не съм създал, това единствената част, която е моят код, е действието void в рамките на Class Restart. Така че имам файл, който съдържа имена на някои класове като ThermostatNight с номер на време на забавяне, така че трябва да прочета всеки ред и да създам събитието.   -  person Woody008    schedule 12.12.2015


Отговори (2)


Не можете директно да създадете вътрешен клас, както се опитвате да направите. Можете да създадете само обект от тип GreenhouseControls.

person JJF    schedule 11.12.2015

Трябва да подадете Long.TYPE към getDeclaredConstructor, така че да търси ThermostatNight(long). В момента той търси деклариран конструктор, наречен ThermostatNight().

cls = Class.forName("GreenhouseControls$ThermostatNight");
clsCon = cls.getDeclaredConstructor(Long.TYPE);
person Kyle Sletten    schedule 11.12.2015
comment
Идеята ви е правилна, но няма да работи поради две причини, 1: Long.class не е същото като long.class; 2: Имате нужда от екземпляр на външния клас, преди да можете да създадете екземпляр на вътрешния клас - person MadProgrammer; 12.12.2015
comment
Е, ако сте забелязали, използвах Long.TYPE (същото като long.class), а не Long.class. Що се отнася до вътрешната класа, да, това е вярно. - person Kyle Sletten; 12.12.2015
comment
Съжалявам, че забравих да добавя Long.Type в моя код, но все още получавам java.lang.NoSuchMethodException: GreenhouseControls$ThermostatNight.‹init›(long) - person Woody008; 12.12.2015
comment
Съжалявам, по телефона, така че видях само Дългия, лошо ми е - person MadProgrammer; 12.12.2015