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

java编程思想学习笔记(6)--手动创建、编译、运行Java程序

2017-03-24 20:50 711 查看
看到第六章的包这部分的内容,当自己创建,并手动编译、运行Java程序时遇到了一些问题

对于单个java源程序,没有引用其他的类时,可以直接在类所在的目录下进行编译运行。

先来看一个简单程序:

//当前目录为C:/Users/lzy/Desktop/package2
// package package2;
public class Main{
public static void main(String args[]){
System.out.println("Hello Java");
}
}


通过命令行来编译、运行,结果如下:



其中,-cp/-classpath 用于指定类路径,Java解释器会通过-cp指定的classpath来寻找.class文件,“.”表示当前路径(”..”表示上一层目录),也可以用绝对路径来指定,没有指定classpath时会出现”找不到或无法加载主类…“的错误。也可以在windows的系统环境变量中配置CLASSPATH,这样就可以不用每次都使用-cp参数

如果给上面的程序加上package关键字时,编译运行又会不同,如下图:



这里指定了类路径还是找不到主类,解决这个问题之前,先来看一下java解释器的运行过程

先找出classpath,classpath包含的目录作为查找.class文件的根目录

Java解释器获取包的名称,并将每个句点替换成反斜杠,以从classpath中产生一个路径名称(示例中是package2,只有一层,不用替换)

将得到的路径与classpath中的各个不同的项连接,得到不同的路径,解释器会在这些目录下寻找与你所要创建的类名称相关的.class文件

对于使用”java -cp . Main”来运行Main程序时,java解释器会得到一个C:\Users\lzy\Desktop\package2\package2的文件夹,它在当前文件夹(下图中package2)中寻找package2时,发现找不到,所以返回错误。



所以要正确运行当前程序,要指定classpath为package指定的目录的上一层目录(在这个示例中为Desktop),运行结果如下:



上面所说的都是单个java文件的情况,当一个.java文件的类中引用另一个.java文件的类时,情况又会复杂很多。

处于同一个文件夹下的所有.java文件,默认属于同一个默认包(即未命名包),所以它们可以直接访问对方的除了private修饰之外的所有成员。

看下面两个同处于package2文件夹中的程序:

//当前目录为C:/Users/lzy/Desktop/package2

public class Main{
public static void main(String args[]){
Second sec=new Second();
sec.f();
}
}


//当前目录为C:/Users/lzy/Desktop/package2

public class Second{
void f(){
System.out.println("Second.sec()");
}
}


程序运行结果如下,可以看到Main类直接调用了Second类的f()方法:



如果直接编译,而不指定classpath,会出现找不到符号的错误

java编译器默认的classpath是当前目录,如果没有指定classpath,编译器会在当前目录中查找java源文件,所以前面的两个例子能够在不指定classpath时编译成功,但是当类中引用了另一个Java文件的类时,它找不到引用的那个类,可能是因为默认的classpath只能用于查找要编译的那个类,不能用于引用的类,如果使用”javac Main.java Second.java”或者”javac *.java”来编译的话能够编译成功(这只是我的猜想,正确与否有待验证)

处于不同文件夹的java源文件,如果没有指定package,它们也都是属于同一个默认包的,也都可以直接互相访问对方除了private之外的成员。

下面用两个分别属于不同文件夹的java源文件来演示,文件的树结构如下:



//当前目录为C:/Users/lzy/Desktop/package2

public class Main{
public static void main(String args[]){
//在main()类中调用Test类的函数
Test1 test1=new Test1();
test1.f();
}
}


//当前目录为C:/Users/lzy/Desktop/temp/package1
public class Test1{
void f(){
System.out.println("Test1");
}
}


运行结果如下图:



这里既要指定Test的目录,也要指定当前目录”.”,因为当使用-cp指定目录时,默认的目录会被覆盖。

如果程序中指定了package,则要引用该类就必须使用关键字import来使package中的名称可用,另一个选择是给出包括package在内的完整的名称。

给上面的Test1类加上”package temp.package1;”,并将f()方法改为public修饰,Main类改为如下代码:

//当前目录为C:/Users/lzy/Desktop/package2
public class Main{
public static void main(String args[]){
//使用import的话,就可以不用写类前面的那些很长的包名
temp.package1.Test1 test1=new temp.package1.Test1();
test1.f();
}
}


程序运行结果如下:



这里,因为Test1类的package为temp.package1,所以,指定classpath时,只能指定tmep目录的上一层目录即Desktop目录,还有因为Main类和Test1类属于不同的package,所以只能访问Test1类的public修饰的成员。

如果想要将编译生成的.class文件放到某个特定的目录,可以使用-d 参数

如果程序中没有package,则生成的.class文件会直接放到-d指定的目录下

如果程序指定了package,则编译器会在-d指定的目录下创建package所指定的路径

还是使用上面的的Main和Test1程序来示例,将.class保存到package2文件夹下面的out文件夹,运行结果如下图



编译后生成的文件目录树如下:



可以看到,在out目录下创建了temp/package1文件夹
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息