【问题标题】:Unable to instantiate class using Class.forName() [duplicate]无法使用 Class.forName() 实例化类 [重复]
【发布时间】:2015-12-11 21:10:11
【问题描述】:

我在使用 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();
 }  
}

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

【问题讨论】:

  • ThermostatNight 是 GreenhouseControls 的一个实例内部类,为了创建它的实例,您需要一个外部类 GreenhouseControls 的实例
  • 发布重现问题所需的最少代码。此外,由于ThermostatNight 是内部类,因此您需要外部类实例来实例化它。
  • 不清楚为什么要使用非静态内部类,以及为什么首先需要反射。将类放在默认包中也是一种非常糟糕的做法。你想达到什么目标?在这里使用反射的目的是什么?
  • 嗯,这是我没有构建的作业,唯一的部分是我的代码是类重启中的 void 操作。所以我有一个文件,其中包含一些类名,例如带有延迟时间编号的 ThermostatNight,因此我必须读取每一行并创建事件。

标签: java class reflection constructor


【解决方案1】:

您不能像尝试那样直接创建内部类。您只能创建 GreenhouseControls 类型的对象。

【讨论】:

    【解决方案2】:

    您必须将Long.TYPE 传递给getDeclaredConstructor,以便它查找ThermostatNight(long)。目前它正在寻找一个名为 ThermostatNight() 的已声明构造函数。

    cls = Class.forName("GreenhouseControls$ThermostatNight");
    clsCon = cls.getDeclaredConstructor(Long.TYPE);
    

    【讨论】:

    • 你的想法是对的,但是行不通有两个原因,1:long.class 和long.class 不一样; 2:需要外部类的实例,才能创建内部类的实例
    • 好吧,如果你注意到了,我使用了Long.TYPE(与long.class 相同)而不是Long.class。至于内部阶层的事情,是的,这是真的。
    • 对不起,我忘了在我的代码中添加 Long.Type 但我仍然收到 java.lang.NoSuchMethodException: GreenhouseControls$ThermostatNight.(long)
    • 对不起,在电话里,所以我只看到了龙。,我的坏
    猜你喜欢
    • 1970-01-01
    • 2011-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-19
    • 2017-01-17
    • 2012-12-19
    • 2020-09-11
    相关资源
    最近更新 更多