(第一次写这种文章,不妥之处希望大家偷偷笑笑就行了)
使用import语句在编译的时候无法找到包:
(文件的存放目录:F:\Program Files\apache-tomcat-7.0.35\webapps\webDemo\WEB-INF\src\lee 以后简写为F:\Program Files\...\src\lee)
excute.java (目录:F:\Program Files\...\src\lee)
package lee;
import test.myString;
public class excute{
public static void main(String[] args){
myString ms = new myString("chenqiao");
System.out.println("result : " + ms.name);
}
}
myString.java (目录:F:\Program Files\...\src\test)
package test;
public class myString{
public String name;
public myString(){}
public myString(String name){
this.name = name ;}
}
当我们在
F:\Program Files\...\src\lee编译excute文件的时候就会出现找不到类的错误
F:\Program Files\...\src\lee>javac excute.java
excute.java:2: 错误: 程序包test不存在
import test.myString;
^
excute.java:5: 错误: 找不到符号
myString ms = new myString("chenqiao");
^
符号: 类 myString
位置: 类 excute
excute.java:5: 错误: 找不到符号
myString ms = new myString("chenqiao");
^
符号: 类 myString
位置: 类 excute
3 个错误
然而在 F:\Program Files\...\src\test下编译myString时去可以找到
看到这里我不知道大家是否有了答案,下面再给出一个测试的列子,相信大家就有答案了。
../ 是返回上级目录
同样编译lee下的excute.java,得到一样的错误
F:\Program Files\...\src\lee>javac ../lee/excute.java
excute.java:2: 错误: 程序包test不存在
import test.myString;
^
excute.java:5: 错误: 找不到符号
myString ms = new myString("chenqiao");
^
符号: 类 myString
位置: 类 excute
excute.java:5: 错误: 找不到符号
myString ms = new myString("chenqiao");
^
符号: 类 myString
位置: 类 excute
3 个错误
编译test下的myString.java是能够成功的。
相信这里聪明的你有答案了吧。运行时的情况也是这样了只是javac变成了java而已。
javac 与 java 执行的时候在当前路径下面,若一个java文件中有import语句的话,编译器也是在当前路径下面去检索的。若当前路径下面没有对应的包,当然就会报错test包无法找到的错误了,所以即使../返回上级目录,但是import去检索的路径依然为发生改变(暂时还没研究过怎么解决,知道的朋友请告诉一下嘛!)。
下面的方法就是正确的方法了,IDE等等也是按照下面的原理去编译于运行的吧(猜测、、、、o(╯□╰)o)
F:\Program Files\apache-tomcat-7.0.35\webapps\webDemo\WEB-INF\src>javac lee/excu
te.java
F:\Program Files\apache-tomcat-7.0.35\webapps\webDemo\WEB-INF\ src>java lee.excut
e
result : chenqiao
————————————————————————————————————————————————————————————————————————————
现在说以一下package的这个东西,然后大家就知道为什么在运行时要输入(java编译后的文件目录:F:\Program Files\...\classes)
F:\Program Files\...\classes>java lee.excute
package就像是父亲给孩子取名字:
lee下class:excute文件的第一行 package lee;就是说这个类 姓lee 名excute (lee.excute)
当然也有复姓,就像外国人的小孩子,爷爷的爸爸的姓没准有4个5个的(就是包名啦)
比如说 java.lang.String,就是复姓 java.lang,名字为 String 的类别
import则是为了解决下面2个问题。
1.重名
如果在src下面分别test1、test2、test3三个包,而包下都有一个叫做myString的类(可能是由张三、李四、王五分别写的)
我在excute下面直接写 myString s1 = new myString();(先不管报错的机制哈)
若编译器都找到这个3个类,问题就出现,它是去new 张三的 还是李四的呢? 而程序员也会有这样是李四的还是张三的呢?
有了import就好理解多了,比如 import test1.myString;这个时候编译器和程序员都知道这个是张三而不是李四了。
2.复姓即报名太长
import java.lang.System;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
是不是有点难得写呢,下面import来给大家瘦身了import java.lang.*;
import java.io.*;
但若是太瘦也会出问题的 import java.*;当然import 和 C/C++里面的#Include可是有很大的不同哦!
import 的功能到此为止,它不像 #include 一样,会将档案内容载入进来。import 只是请编译器帮你打字,让编译器把没有姓的类别加上姓,并不会把别的文件的程式码写进来。如果你想练习打字,可以不要使用 import,只要在用到类别的时候,用它的全部姓名来称呼它就行了(就像例子一开始那样),跟使用 import 完全没有甚么两样。
另外,虽然人不可以太懒,但是 Sun 还是帮我们多偷了一点懒。因为java.lang 这个套件实在是太常太常太常用到了,几乎没有程序不用它的,所以不管你有没有写 import java.lang;,编译器都会自动帮你补上,也就是说编译器只要看到没有姓的类别,它就会自动去 java.lang 里面找找看,看这个类别是不是属于这个套件的。所以我们就不用特别去
import java.lang 了。