【发布时间】: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