在 java 的特定文件夹中加载不知道名称的 class
load a class without knowing name in a specific folder in java
我有一个 java 应用程序,它在文件中执行一些操作并发布结果输出。我想添加一个 属性,每个使用我的应用程序的人都可以添加 his/her 特定的运算符。并且知道我想在不知道其名称或方法的情况下加载 class。
这是我的 class,我知道 class 和可能添加的方法名称:
public class PathGetter {
public static void main(String[] args) {
try{
String AbsolutePath = args[0];
AbsolutePath += "\in.txt";
String SecondFilePath = args[1];
SecondFilePath += "\out.txt";
File file = new File(SecondFilePath);
file.createNewFile();
FileWriter writer = new FileWriter(file);
FileReader fr = new FileReader();
Object newOp = null;
String newOpSign="!@#$%^&*";
Method m = null;
MathOperations mathOperations = new MathOperationsImpl();
System.out.println("Do you have new operator? ");
Scanner scanner1 = new Scanner(System.in);
if(scanner1.nextBoolean()==true){
Scanner scanner2 = new Scanner(System.in);
System.out.println("Enter operator sign: ");
newOpSign = scanner2.nextLine();
File addedClass= new File("E:\workspace\940420\bin");
URI uri = addedClass.toURI();
URL[] urls = new URL[]{uri.toURL()};
ClassLoader classLoader = new URLClassLoader(urls);
Class clazz = classLoader.loadClass("second.MathOperationsUpdateImpl"); \I don't know the class name might be added
newOp = clazz.newInstance();
m = newOp.getClass().getMethod("mathOperate", String.class); \I don't know the method name in added class
}
ArrayList<String> answer = new ArrayList<String>();
for (int i = 0; i < fr.readFile(AbsolutePath).size(); i++) {
if((fr.readFile(AbsolutePath).get(i)).contains(newOpSign)){
answer.add(i, String.valueOf(m.invoke(newOp,(fr.readFile(AbsolutePath).get(i)))));
}
else{
answer.add(i, String.valueOf(mathOperations.mathOperate(fr.readFile(AbsolutePath).get(i))));
}
}
for (int i = 0; i < fr.readFile(AbsolutePath).size(); i++) {
writer.write(answer.get(i)+ "\r\n");
}
writer.close();
System.out.print("Your File Successfully Created In: " + SecondFilePath);
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
}
}
}
评论总结给出最终答案:
1:如果不知道class名字,可以用File获取目录内容:
File d = new File("<knowDirectory>");
File[] f = d.listFiles();
当然,目录下应该只有一个.class
文件。
2.: 所以你知道class文件的名称和路径。用
加载它
Class c = Class.forName("<classname>").
你也可以通过反射获得所有可用的方法:
Methods[] m = c.getMethods();
3(A).: 如果您不知道要调用的方法的名称,但它的签名(即 return 类型和参数),您可以使用 m.getReturnType()
和 m.getParameterTypes()
来查找具有指定签名的方法。如果有多个,则无法区分它们。如果只有一个带有签名的方法就使用它(通过反射调用)。像这样(对于 return 类型 Double
和单个参数 String
):
Class<?>[] params = m.getParameterTypes();
Class<?> r = m.getReturnType();
if(r.getName().equals(Double.class.getName())
&& params.length == 1
&& params[0].getName().equals(String.class.getName()))
{
// invoke
}
3(B).: 如果你强制用户实现一个抽象 class (或接口),那么你知道方法的名称实现,加载 class 并将其转换为接口:
Class childClass = Class.forName("DerivedClassName");
MyAbstractClass userOperator = (MyAbstractClass)childClass.newInstance();
我有一个 java 应用程序,它在文件中执行一些操作并发布结果输出。我想添加一个 属性,每个使用我的应用程序的人都可以添加 his/her 特定的运算符。并且知道我想在不知道其名称或方法的情况下加载 class。
这是我的 class,我知道 class 和可能添加的方法名称:
public class PathGetter {
public static void main(String[] args) {
try{
String AbsolutePath = args[0];
AbsolutePath += "\in.txt";
String SecondFilePath = args[1];
SecondFilePath += "\out.txt";
File file = new File(SecondFilePath);
file.createNewFile();
FileWriter writer = new FileWriter(file);
FileReader fr = new FileReader();
Object newOp = null;
String newOpSign="!@#$%^&*";
Method m = null;
MathOperations mathOperations = new MathOperationsImpl();
System.out.println("Do you have new operator? ");
Scanner scanner1 = new Scanner(System.in);
if(scanner1.nextBoolean()==true){
Scanner scanner2 = new Scanner(System.in);
System.out.println("Enter operator sign: ");
newOpSign = scanner2.nextLine();
File addedClass= new File("E:\workspace\940420\bin");
URI uri = addedClass.toURI();
URL[] urls = new URL[]{uri.toURL()};
ClassLoader classLoader = new URLClassLoader(urls);
Class clazz = classLoader.loadClass("second.MathOperationsUpdateImpl"); \I don't know the class name might be added
newOp = clazz.newInstance();
m = newOp.getClass().getMethod("mathOperate", String.class); \I don't know the method name in added class
}
ArrayList<String> answer = new ArrayList<String>();
for (int i = 0; i < fr.readFile(AbsolutePath).size(); i++) {
if((fr.readFile(AbsolutePath).get(i)).contains(newOpSign)){
answer.add(i, String.valueOf(m.invoke(newOp,(fr.readFile(AbsolutePath).get(i)))));
}
else{
answer.add(i, String.valueOf(mathOperations.mathOperate(fr.readFile(AbsolutePath).get(i))));
}
}
for (int i = 0; i < fr.readFile(AbsolutePath).size(); i++) {
writer.write(answer.get(i)+ "\r\n");
}
writer.close();
System.out.print("Your File Successfully Created In: " + SecondFilePath);
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
}
}
}
评论总结给出最终答案:
1:如果不知道class名字,可以用File获取目录内容:
File d = new File("<knowDirectory>");
File[] f = d.listFiles();
当然,目录下应该只有一个.class
文件。
2.: 所以你知道class文件的名称和路径。用
加载它Class c = Class.forName("<classname>").
你也可以通过反射获得所有可用的方法:
Methods[] m = c.getMethods();
3(A).: 如果您不知道要调用的方法的名称,但它的签名(即 return 类型和参数),您可以使用 m.getReturnType()
和 m.getParameterTypes()
来查找具有指定签名的方法。如果有多个,则无法区分它们。如果只有一个带有签名的方法就使用它(通过反射调用)。像这样(对于 return 类型 Double
和单个参数 String
):
Class<?>[] params = m.getParameterTypes();
Class<?> r = m.getReturnType();
if(r.getName().equals(Double.class.getName())
&& params.length == 1
&& params[0].getName().equals(String.class.getName()))
{
// invoke
}
3(B).: 如果你强制用户实现一个抽象 class (或接口),那么你知道方法的名称实现,加载 class 并将其转换为接口:
Class childClass = Class.forName("DerivedClassName");
MyAbstractClass userOperator = (MyAbstractClass)childClass.newInstance();