外部Java文件导入自定义类后无法被主程序编译的问题
问题描述
我正在开发一个需要编译并执行外部包中Java文件的程序。遇到的问题是:当外部文件导入自定义的Robot类时,主程序无法编译该外部文件;移除该导入语句后,编译可正常进行。
主类代码
package zhrfrd.jrobots; import java.awt.Color; import java.awt.Dimension; import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; public class JRobots { public static void main(String[] args) throws IOException { // Compile and execute external java program try { Process processCompilation = Runtime.getRuntime().exec("javac -d /Users/faridzouheir/eclipse-workspace/JRobots/src/ /Users/faridzouheir/eclipse-workspace/JRobots/src/zhrfrd/testjrobots/Test.java"); // Compile Test.java processCompilation.waitFor(); // Wait until the process is terminated before starting the following process (to avoid the second process not working properly) Process processExecution = Runtime.getRuntime().exec("java -cp /Users/faridzouheir/eclipse-workspace/JRobots/src/ zhrfrd.testjrobots.Test"); // Execute java (-cp is class path) BufferedReader in = new BufferedReader(new InputStreamReader(processExecution.getInputStream())); // Get result of the execution of the external file String line = null; while ((line = in.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); System.out.println("Execution error."); } catch (InterruptedException e) { e.printStackTrace(); System.out.println("Interrupted exception."); } } }
待执行的外部文件(Test)代码
package zhrfrd.testjrobots; import java.io.IOException; import zhrfrd.jrobots.Robot; // 就是这个导入语句导致编译失败 public class Test{ private static final long serialVersionUID = 1L; static Robot rob; public static void main(String[] args) throws IOException { Robot rob; int a = 300; int b = 23; int res = doSum(a, b); System.out.println(res); // boom(); rob = new Robot(); rob.boom(); } public static int doSum(int a, int b) { return a + b; } }
Robot类代码
package zhrfrd.jrobots; import java.awt.Dimension; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.Random; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JLabel; public class Robot extends JLabel implements Runnable{ protected static final long serialVersionUID = 1L; protected int life, direction, speed, posX, posY; protected Thread threadRobot; private Random random; private Dimension size; // Constructor public Robot() throws IOException { this.life = 100; threadRobot = new Thread(this, "My thread"); } // Methods //Set robot position public void setPosition() { random = new Random(); posX = random.nextInt(500); posY = random.nextInt(500); size = this.getPreferredSize(); this.setBounds(posX, posY, size.width, size.height); System.out.println(posX); } //TEST METHOD public void boom() { System.out.println("BOOM BOOM!!"); } @Override public void run () { System.out.println(threadRobot.getName()); setPosition(); } }
补充说明
- 曾尝试将Robot类移至Test所在的同一包中,但问题仍未解决。
- 若移除Test类的main方法并将其改为Robot的子类,是否仍可编译并执行?
解决方案
1. 修复编译命令的类路径问题
你当前的编译命令只传入了Test.java,但编译器找不到依赖的Robot类。需要给javac指定类路径,或者同时编译依赖的源文件:
方式一:指定类路径(适用于Robot已编译的情况)
修改编译命令为:
javac -d /Users/faridzouheir/eclipse-workspace/JRobots/src/ -cp /Users/faridzouheir/eclipse-workspace/JRobots/src/ /Users/faridzouheir/eclipse-workspace/JRobots/src/zhrfrd/testjrobots/Test.java
-cp参数告诉编译器去哪里找Robot类的字节码文件。
方式二:同时编译两个源文件(适用于Robot未编译的情况)
javac -d /Users/faridzouheir/eclipse-workspace/JRobots/src/ /Users/faridzouheir/eclipse-workspace/JRobots/src/zhrfrd/jrobots/Robot.java /Users/faridzouheir/eclipse-workspace/JRobots/src/zhrfrd/testjrobots/Test.java
2. 移包后仍失败的处理
把Robot移到Test同包后,先清理src目录下所有旧的.class文件,再重新编译,避免旧字节码导致的路径混淆。
3. 改为Robot子类的可行性
完全可以,但需要调整执行逻辑:
- 修改Test类为Robot的子类:
package zhrfrd.testjrobots; import java.io.IOException; import zhrfrd.jrobots.Robot; public class Test extends Robot { private static final long serialVersionUID = 1L; public Test() throws IOException { super(); } public static int doSum(int a, int b) { return a + b; } }
- 由于Test类没有main方法,不能直接用
java命令执行,需要在JRobots类中通过反射或者直接实例化的方式调用该子类,比如:
// 在JRobots的main方法中,编译后添加以下逻辑 Class<?> testClass = Class.forName("zhrfrd.testjrobots.Test"); Robot testRobot = (Robot) testClass.getConstructor().newInstance(); testRobot.boom();
内容的提问来源于stack exchange,提问作者zhrfrd
相关产品推荐
相关产品推荐

