Java源文件编译问题汇总

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值