关于JAVA项目中CLASSPATH路径详解

自己看完总结:配置中"classpath: " 相当于输出目录,即编译后的class文件 所在目录;而 "file:" 是 启动目录而言,14 上服务器就是WEB-INF 下目录,本地项目就是项目根目录。

关于JAVA项目中CLASSPATH路径详解
分类: Java 2013-03-14 10:52 6845人阅读 评论(1) 收藏 举报
在dos下编译java程序,就要用到classpath这个概念,尤其是在没有设置环境变量的时候。classpath就是存放.class等编译后文件的路径。

javac:如果当前你要编译的java文件中引用了其它的类(比如说:继承),但该引用类的.class文件不在当前目录下,这种情况下就需要在javac命令后面加上-classpath参数,通过使用以下三种类型的方法 来指导编译器在编译的时候去指定的路径下查找引用类。

(1).绝对路径:javac -classpath c:/junit3.8.1/junit.jar   Xxx.java
(2).相对路径:javac -classpath ../junit3.8.1/Junit.javr  Xxx.java
(3).系统变量:javac -classpath %CLASSPATH% Xxx.java (注意:%CLASSPATH%表示使用系统变量CLASSPATH的值进行查找,这里假设Junit.jar的路径就包含在CLASSPATH系统变量中)
javac 绝对路径的使用:

javac:假设你要编译的类文件名叫:HelloWorld.java,其完全路径为:D:/java/HelloWorld.java。但你所在的当前目录是:C:/Documents and Settings/peng>。如果想在这里执行编译,会有什么结果呢?

(1).C:/Documents and Settings/peng> javac HelloWorld.java 这时编译器会给出如下的错误提示信息:
error: cannot read: HelloWorld.java
这是因为默认情况下javac是在当前目录下查找类文件,很明显这个路径不是我们存放类文件的地方,所以就会报错了

(2).C:/Documents and Settings/peng>javac D:/java/HelloWorld.java
这时编译成功。
所以,只要你执行javac命令的目录不是类文件存放的目录,你就必须在javac命令中显式地指定类文件的路径。

java -classpath的使用:

java:假设我们的CLASSPATH设置为:D:/peng/java/pro ,在该目录下有三个文件:HelloWorld.java / HelloWorldExtendsTestCase / HelloWorldExtendsHelloWorld。这三个文件的类声明分别如下:

HelloWorld.java :public class HelloWorld
HelloWorldExtendsHelloWorld.java :public class HelloWorldExtendsHelloWorld extends HelloWorld
HelloWorldExtendsTestCase.java:public class HelloWorldExtendsTestCase extends junit.framework.TestCase 

      假设我们已经按照上面关于javac -classpath和javac 绝对路径的使用,顺利地完成了三个文件地编译。现在我们在C:/Documents and Settings/peng>目录下执行这三个.class文件

(1).C:/Documents and Settings/peng>java  HelloWorld
      Hello World

可以看到执行成功。为什么我们在 C:/Documents and Settings/peng>执行命令,JVM能够找到D:/peng/java/pro/HelloWorld.class文件呢?这是因为我们配置了系统变量CLASSPATH,并且指向了目录:D:/peng/java/pro 。所以JVM会默认去该目录下加载类文件,而不需要指定.class文件的绝对路径了。

(2).C:/Documents and Settings/peng>java HelloWorldExtendsHelloWorld
       Hello World

可以看到执行成功了。HelloWorldExtendsHelloWorld继承了HelloWorld类,所以在执行时JVM会先查找在CLASSPATH下是否存在一个HelloWorld.class文件,因为我们已经成功编译了HelloWorld 类了,所以可以成功执行HelloWorldExtendsHelloWorld.class

(3).C:/Documents and Settings/peng>java HelloWorldExtendsTestCase
     Exception in thread "main" java.lang.NoClassDefFoundError: junit/framework/TestCase
可以看到程序抛出异常了,提示找不到junit.framework.TestCase文件。为什么同样在:/peng/java/pro 下,HelloWorldExtendsHelloWorld.class就可以成功执行,而这个就不行了呢?这是因为:            junit.framework.TestCase.class文件并不存在于当前目录下,所以为了能够让程序成功运行,我们必须通过指定CLASSPATH的方式,让JVM可以找到junit.framework.TestCase这个类,如(4):
(4). C:/Documents and Settings/peng>java -classpath %CLASSPATH% HelloWorldExtendsTestCase
      Hello World
总结:
(1).何时需要使用-classpath:当你要编译或执行的类引用了其它的类,但被引用类的.class文件不在当前目录下时,就需要通过-classpath来引入类
(2).何时需要指定路径:当你要编译的类所在的目录和你执行javac命令的目录不是同一个目录时,就需要指定源文件的路径(CLASSPATH是用来指定.class路径的,不是用来指定.java文件的路径的) 

JAVA获取classpath路径:

ClassLoader 提供了两个方法用于从装载的类路径中取得资源:

        public URL  getResource (String name);
        public InputStream  getResourceAsStream (String name);  

       这里name是资源的类路径,它是相对与“/”根路径下的位置。getResource得到的是一个URL对象来定位资源,而getResourceAsStream取得该资源输入流的引用保证程序可以从正确的位置抽取数据。
       但是真正使用的不是ClassLoader的这两个方法,而是Class的 getResource和getResourceAsStream方法,因为Class对象可以从你的类得到(如YourClass.class或 YourClass.getClass()),而ClassLoader则需要再调用一次YourClass.getClassLoader()方法,不过根据JDK文档的说法,Class对象的这两个方法其实是“委托”(delegate)给装载它的ClassLoader来做的,所以只需要使用 Class对象的这两个方法就可以了。

       因此,直接调用  this.getClass().getResourceAsStream(String name) ;获取流,静态化方法中则使用ClassLoader.getSystemResourceAsStream (String name) ; 。

      下面是一些得到classpath和当前类的绝对路径的一些方法。你可能需要使用其中的一些方法来得到你需要的资源的绝对路径。

1.this.getClass().getResource("")
得到的是当前类class文件的URI目录。不包括自己!
如:file:/D:/workspace/jbpmtest3/bin/com/test/

2.this.getClass().getResource("/")
得到的是当前的classpath的绝对URI路径 。
如:file:/D:/workspace/jbpmtest3/bin/

3.this.getClass() .getClassLoader().getResource("")
得到的也是当前ClassPath的绝对URI路径 。
如:file:/D:/workspace/jbpmtest3/bin/

4.ClassLoader.getSystemResource("")
得到的也是当前ClassPath的绝对URI路径 。
如:file:/D:/workspace/jbpmtest3/bin/

5.Thread.currentThread().getContextClassLoader ().getResource("")
得到的也是当前ClassPath的绝对URI路径 。
如:file:/D:/workspace/jbpmtest3/bin/

6.ServletActionContext.getServletContext().getRealPath(“/”)
Web应用程序 中,得到Web应用程序的根目录的绝对路径。这样,我们只需要提供相对于Web应用程序根目录的路径,就可以构建出定位资源的绝对路径。
如:file:/D:/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/WebProject

注意点:

1.尽量不要使用相对于System.getProperty("user.dir")当前用户目录的相对路径。这是一颗定时炸 弹,随时可能要你的命。

2.尽量使用URI形式的绝对路径资源。它可以很容易的转变为URI,URL,File对象。

3.尽量使用相对classpath的相对路径。不要使用绝对路径。使用上面ClassLoaderUtil类的public static URL getExtendResource(String relativePath)方法已经能够使用相对于classpath的相对路径定位所有位置的资源。

4.绝对不要使用硬编码的绝对路径。因为,我们完全可以使用ClassLoader类的getResource("")方法得到当前classpath的绝对路径。如果你一定要指定一个绝对路径,那么使用配置文件,也比硬编码要好得多!

获得CLASSPATH之外路径的方法:
URL base = this.getClass().getResource(""); //先获得本类的所在位置,如/home/popeye/testjava/build/classes/net/
      String path = new File(base.getFile(), "……/……/……/"+name).getCanonicalPath(); //就可以得到/home/popeye/testjava/name

另外,如果从ANT启动程序,this.getClass().getResource("")取出来的比较怪,直接用JAVA命令行调试就可成功。

PS:以上内容很多来自转载和自己的部分总结。
时间: 2024-10-29 10:46:25

关于JAVA项目中CLASSPATH路径详解的相关文章

《Java项目中classpath路径详解》

项目里用到了classpath路径来引用文件,那么classpath指的是哪里呢 我首先把上面的applicationContext.xml文件放在了src目录下发现可以. 那么classpath到底是哪里呢,在网上看了几篇博客 画黄线部分解释了我放在src目录下能用classpath:访问的问题. 但是红线部分,他说这句话对,我感觉有问题. 然后我就试了一下 发现无论是放在WEB-INF目录下,还是WEB-INF/lib下都不行.WEB-INF/classes文件还没有..... 然后去项目W

eclipse项目中.classpath文件详解

1 前言 在使用eclipse或者myeclipse进行Java项目开发的时候,每个project(工程)下面都会有一个.classpath文件,那么这个文件究竟有什么作用? 2 作用 .classpath文件用于记录项目编译环境的所有信息,包括:源文件路径.编译后class文件存放路径.依赖的jar包路径.运行的容器信息.依赖的外部project等信息.如果把该文件删除,则eclipse不能讲该工程识别为一个正常的java工程,仅仅当做普通的文件夹而导致不能正常运行. 3 .classpath

java项目中classpath路径到底指的是哪里?

本文转自:http://blog.csdn.net/javaloveiphone/article/details/51994268 1.src不是classpath, WEB-INF/classes和lib才是classpath,WEB-INF/ 是资源目录, 客户端不能直接访问. 2.WEB-INF/classes目录存放src目录java文件编译之后的class文件,xml.properties等资源配置文件,这是一个定位资源的入口. 3.引用classpath路径下的文件,只需在文件名前加

【java项目实战】Servlet详解以及Servlet编写登陆页面(二)

Servlet是Sun公司提供的一门用于开发动态web网页的技术.Sun公司在API中提供了一个servlet接口,我们如果想使用java程序开发一个动态的web网页,只需要实现servelet接口,并把类部署到web服务器上就可以运行了. 到底什么是Servlet呢? 通俗一点,只要是实现了servlet接口的java程序,均称Servlet.Servlet是由sun公司命名的,Servlet = Server + Applet(Applet表示小应用程序),Servlet是在服务器端运行的小

Java NIO中的Buffer 详解

Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的.缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存. Buffer的基本用法使用Buffer读写数据一般遵循以下四个步骤: 写入数据到Buffer    调用flip()方法    从Buffer中读取数据    调用clear()方法或者compact()方法 当向buffer写入数据时,

Java web中WEB-INF目录详解

1.它是java的web应用的安全目录.所谓安全就是客户端无法访问,只有服务端可以访问的目录. 2.web.xml项目部署文件. 3.classes文件夹,用以防止*.class文件 4.lib文件夹,用于存放需要的jar包. WEB-INF中配置web.xml文件,添加<welcome-file-list> <welcome-file> 设定的首页文件名 <welcome-file> <welcome-fiel-list>

关于web.xml中classpath*的详解

web.xml:contextConfigLocation/WEB-INF/spring-configuration/.xml/WEB-INF/deployerConfigContext.xml classpath:/META-INF/spring/*.xml 详细请参照:http://blog.csdn.net/zl3450341/article/details/9306983

Java多线程中join方法详解

join()方法用于让当前执行线程等待join线程执行结束.其实现原理是不停的检查join线程是否存活,如果join线程存活则让当前线程永远等待. join()方法部分实现细节 while(isAlive()) { wait(0) } 其中wait(0)表示永远等待下去. join线程中止后,线程的this.notifyAll()方法会被调用,调用notifyAll()是在JVM里调用的所有在JDK中看不到,大家可以看JVM源码 示例程序: public calss ThreadTest{ pu

在 Java 项目中解压7Zip特殊压缩算法文件

1 问题描述 Java Web 后端下载了一个经特殊算法压缩的 zip 文件,因为不能采用 java 本身自带的解压方式,必须采用 7Zip 来解压.所以,提到了本文中在 java web 后端调用外部 7zip exe 来解压文件的问题. 2 主要实现 2.1 定义缓冲区类 class StreamGobbler extends Thread { InputStream is; String type; public StreamGobbler(InputStream is, String t