您的位置:首页 > 编程语言 > Java开发

Java源文件编译问题汇总

2016-07-05 16:59 429 查看
Java编程语言、J2SE、J2EE等教程在入门阶段基本均未使用IDE,编译源文件时基本都是采用命令行编译的方式。这就造成像我一样的Java初学者,在一步一步按照教程上操作之后仍然无法编译成功的情况。后果就是有些人可能就此放弃学习Java,或者只是简单百度一下,无果后要么放弃要么改用其他教程。而我相信一个真正爱好编程、爱好钻研的人都不会对遇见的问题不了了之、视而不见。

无论如何,作为一个Java Web初学者的我,会把从今天开始学习Java Web的一点点心得和经验分享给大家,希望能够有所帮助。闲言少叙,让我们进入今天的主题——Java源文件编译问题汇总。

假设我的工作目录为一个叫做test的文件夹,后续文章除非特殊说明,否则的话工作均是从test文件夹下展开。首先就让我们先从最简单的情况入手。

我有一个java源文件叫做“Test.java”,我把它存放在C:\test\目录下,它的功能只是向控制台输出“Welcome!”,源代码如下所示:
//Test.java
public class Test
{
public static void main(String[] args)
{
System.out.printf("Welcome!");
}
}


当然,首先我要先使用cd C:\test命令设置当前的工作目录。之后,相信每个Java-er都会使用javac Test.java命令来编译,编译成功!编译后的目录结构如下图所示。



在继续分享后续内容之前,我需要简单介绍以下javac的-d参数。一言以蔽之——-d参数用于将编译产生的源文件存入反应包名的指定路径中。仍旧以Test.java文件为例说明,修改后的源代码如下所示:
//Test.java
package com.example.web;
public class Test
{
public static void main(String[] args)
{
System.out.printf("Welcome!");
}
}


通常情况下,我们仍旧会使用javac Test.java命令编译,这个命令默认会把编译的.class文件存放在和源文件相同的目录下。假如此时我使用-d参数来编译这个加入了包的源文件会发生什么呢?我先用javac
-d
. Test.java(其中的.表示将编译产生的.class文件存放在当前目录下)来编译,我们发现会在test目录下产生一个叫做com\example\web的子目录。



按照大多数Java Web教程或者其他的Java类书籍中提到的,我们通常会将编译产生的.class文件存放在项目根目录下的WEB-INF\classes目录下。所以,我在test目录下新建一个叫做classes的文件夹,然后用javac
-d WEB-INF\classes
Test.java编译,编译产生的class文件会存放在WEB-INF\classes目录下的com\exmaple\web目录下,如下图所示:



目前为止,我们知道-d参数可以任意指定编译产生的.class文件的存放路径,甚至可以指定为月球(HaHa...说好的只是简单说一下-d参数的,还是说了这么多废话-_-!!!)。

接下来让我们正式请出今天的主角:依赖于其他类的源文件如何编译,我会把“其他的类”分为两部分来讲解:

1. “其他的类”为自己定义的类;

2. “其他的类”为Servlet或JSP等特殊的类;

让我们先从“其他的类”为自己定义的类开始讲解,假设我现在有一个叫做Rectangle的矩形类,他有两个私有成员分别表示矩形的长度和宽度,还有一个公有成员函数用于返回矩形的面积。另外我还有一个叫做Test的类,Test中的main函数实例化了Rectangle并且调用getArea()函数得到矩形的面积并打印到控制台。以下是这两个类的源代码:
//Rectangle.java
public class Rectangle
{
private int width;
private int height;

Rectangle(int width, int height)
{
this.width = width;
this.height = height;
}

public int getArea()
{
return (this.width * this.height);
}
}

//Test.java
public class Test
{
public static void main(String[] args)
{
Rectangle rect = new Rectangle(5, 10);
System.out.println(rect.getArea());
}
}


假如这两个类在同一个目录下,我们只需使用javac Test.java来编译Test.java即可,编译器会自动识别Rectangle类并编译,以下是编译后的目录结构:



让我们试着把情况变得复杂一些:我们在test下新建一个名为others的目录,并把Rectangle.java源文件移动到others目录下,现在的目录结构如下所示:



现在我们继续使用javac Test.java编译会得到如下图所示的错误,错误信息提示在编译Test.java文件的时候找不到Rectangle类,或者编译器不知道Rectangle符号是什么玩意儿。



这是因为编译器在当前目录下找不到Rectangle.java。现在该是-sourcepath参数闪亮的时候了,这个参数可以自定义被依赖的类的搜索路径。所以现在我们可以使用javac
-sourcepath others Test.java命令来编译,编译后的目录结构如下所示:



让我们继续把情况变得复杂一些,废话少说直接上修改后的目录结构以及源代码:



//Rectangle.java
package bar;

public class Rectangle
{
private int width;
private int height;

public Rectangle(int width, int height)
{
this.width = width;
this.height = height;
}

public int getArea()
{
return (this.width * this.height);
}
}

//Test.java
package foo;
import bar.*;

public class Test
{
public static void main(String[] args)
{
Rectangle rect = new Rectangle(5, 10);
System.out.println(rect.getArea());
}
}


通过-sourcepath参数的讲解后我们不难得出可以通过javac
-sourcepath src src\foo\Test.java来编译。以下是编译后的目录结构:



但是,当我们在做Java Web项目或者其他我不了解的项目的时候,我们都会在项目的目录下建一个classes文件夹专门用于存放编译产生的.class文件,示例的目录结构如下左图所示,通过命令javac
-d classes
-sourcepath src src\foo\Test.java编译后的目录结构如下右图(-_-!!!)所示:





让我们来看看最后一种我在学习孙鑫的Java Web教程中遇到的情况(Test和Rectangle的源代码未作修改,此种情况困扰了我这个Java Web菜鸟很长时间)。目录结构如下所示:



这种情况下无论我们使用javac
-d classes src\Test.java还是javac
-d classes
-sourcepath src src\Test.java都无法编译成功。目前为止我的解决办法是需要根据Test.java和Rectangle.java中的导包的情况手动创建目录结构如下图如所示,然后通过javac
-d classes
-sourcepath src src\foo\Test.java编译即可。

(在这里,我不得不吐槽以下各位Java前辈们在编书时的态度。一万只草泥马在屏幕上奔腾而过~!@#¥%……&*)



最后,这次真的是最后一部分。让我们来讨论一下“其他的类”为Servlet或JSP等特殊的类的情况。这种情况下若要成功编译有两种方式可以选择,第一:设置classpath环境变量;第二:编译的时候手动设置-classpath参数。由于总有那么一些人在设置环境变量的时候出现问题,所以在这里我只介绍一下万能的第二种方法。

我在这里举一个Servet源文件编译的例子(不懂Java Web或者不懂Servlet的朋友们不要太在意,等下我会提示大家重点需要注意的地方)。具体的目录结构如下所示和源代码如下所示:



//BeerSelect.java
package com.example.web;

import com.example.model.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;

public class BeerSelect extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {

//response.setContentType("text/html");
//PrintWriter out = response.getWriter();
//out.println("Beer Selection Advice<br>");

String c = request.getParameter("color");
BeerExpert be = new BeerExpert();
List result = be.getBrands(c);

request.setAttribute("styles", result);
RequestDispatcher view = request.getRequestDispatcher("result.jsp");
view.forward(request, response);

/*
Iterator it = result.iterator();
while(it.hasNext()) {
out.println("<br>try: " + it.next());
}
*/
}
}

//BeerExpert.java
package com.example.model;

import java.util.*;

public class BeerExpert {
public List getBrands(String color) {
List brands = new ArrayList();
if (color.equals("amber")) {
brands.add("Jack Amber");
brands.add("Red Moose");
} else {
brands.add("Jail Pale Ale");
brands.add("Gout Stout");
}
return(brands);
}
}


很明显BeerSelect类继承自HttpServlet类,BeerSelect引用了另外一个包内的BeerExpert类。我们的目标是成功编译BeerSelect.java。

但是,由于编译HttpServlet这个类所需要的jar文件路径是“C:\tomcat-9.0\lib\servlet-api.jar”,若要成功编译BeerSelect.java需要使用-classpath参数手动指定这个api所在的路径。

假设我们的当前目录是BeerV1,编译BeerSelect.java的命令是:javac
-classpath
C:\tomcat-9.0\lib\servlet-api.jar
-d classes
-sourcepath src src\com\example\web\BeerSelect.java,编译后的而目录结构如下所示:



至此,我在学习Java以及Java Web时遇到的关于源文件编译问题已经全部分享完毕,希望多少能够帮助大家。有任何疑问可以通过评论或通过文章最后列出的联系方式联系我,希望大家不吝赐教。

个人邮箱:xueyublue@gmail.com

工作邮箱:xuey@daifuku.com.sg

丘丘号码:905375641
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: