Java的一些小知识:package,import,不同目录下类的调用
这道题一共要建三个目录:C:\myproj\bin、C:\myproj\lib和C:\myproj\classes,也可以自己建所要的目录,三个目录不同就可以了,具体要求如下:
n public的A.class和B.class属于包X.Y,该包存放在C:\myproj\classes中;public的C.class和D.class属于包S.T,把它们打包为E.jar文件中,并存放在C:\myproj\lib中;这些类均有四个方法:public void sayPublic()、private void sayPrivate()、protected void sayProtected()、void sayDefault(),而且都只包含一条语句System.out.println("Hi,"+getClass()+"."+函数权限(public|private|protected|default))。
n Test1.class、Test2.class和Test3.class为测试类(带入口函数),存放在目录C:\myproj\bin下。
n 打包命令:jar cvf K.jar * (注意把子目录S/T也一起打包进去)。
(吐槽下,做实验报告模板的老师或者TA这里对这道题的表述有些混乱 == 至少我是这样感觉的)
实验步骤:
(1) Test1分别创建A和C的一个对象并调用这四个方法,看看哪些方法可以使用,不能使用的就注释掉。
Test1运行截屏:
Test1的源码:
/*因为A.class和C.class不在Test1.java的所在目录中,所以需要引用包进来,
* 自动添加classpath在前之后,表示包位于
* H:\web\实验\java实验\lab3\code\classes\X\Y
* 或
* H:\web\实验\java实验\lab3\code\lib\S\T
* 下*/
import X.Y.*;
import S.T.*;
public class Test1{
public static void main(String[] args){
A a = new A();
a.sayPublic();
//a.sayPrivate();
//a.sayProtected();
//a.sayDefault();
C c = new C();
c.sayPublic();
//c.sayPrivate();
//c.sayProtected();
//c.sayDefault();
}
}
(2)Test2继承B并直接调用它的四个方法,看看哪些方法可以使用,不能使用的就注释掉。
* 在main()中要采用“Test2 test2=new Test2(); test2.sayPublic();”进行调用,直接调用会出现 “无法从静态上下文中引用非静态方法”的错误(因为要调用非静态方法,必须先要创建对象)。
Test2运行截屏:
Test2的源码:
/*因为B.class不在Test1.java的所在目录中,所以需要引用包进来,
* 自动添加classpath在前之后,表示包位于
* H:\web\实验\java实验\lab3\code\classes\X\Y
* 下*/
import X.Y.*;
//import S.T.*;
public class Test2 extends B{
public static void main(String[] args){
Test2 test2 = new Test2();
test2.sayPublic();
test2.sayProtected();
//下面两个无法引用(编译时报错)
//test2.sayPrivate();
//test2.sayDefault();
}
}
(3)Test3继承D并直接调用它的四个方法,看看哪些方法可以使用,不能使用的就注释掉。
Test3运行截屏:
Test3的源码:
/*因为D.class不在Test1.java的所在目录中,所以需要引用包进来,
* 自动添加classpath在前之后,表示包位于
* H:\web\实验\java实验\lab3\code\lib\S\T
* 下*/
//import X.Y.*;
import S.T.*;
public class Test3 extends D{
public static void main(String[] args){
Test3 test3 = new Test3();
test3.sayPublic();
test3.sayProtected();
//同样下面两个无法引用(编译时报错)
//test3.sayPrivate();
//test3.sayDefault();
}
}
(4)A~D类的源程序。
A的源程序:
/*用package语句指明所属包的名称,
* 相当于注释语句,只是告诉人说这些.java或.class在这个子目录下*/
package X.Y;
public class A
{
public void sayPublic()
{
System.out.println("Hi,"+getClass()+ "."+ "public");
}
private void sayPrivate()
{
System.out.println("Hi,"+getClass()+ "."+ "private");
}
protected void sayProtected()
{
System.out.println("Hi,"+getClass()+ "."+ "protected");
}
void sayDefault()
{
System.out.println("Hi,"+getClass()+ "."+ "default");
}
}
B的源程序:
/*用package语句指明所属包的名称,
* 相当于注释语句,只是告诉人说这些.java或.class在这个子目录下*/
package X.Y;
public class B
{
public void sayPublic()
{
System.out.println("Hi,"+getClass()+ "."+ "public");
}
private void sayPrivate()
{
System.out.println("Hi,"+getClass()+ "."+ "private");
}
protected void sayProtected()
{
System.out.println("Hi,"+getClass()+ "."+ "protected");
}
void sayDefault()
{
System.out.println("Hi,"+getClass()+ "."+ "default");
}
}
C的源程序:
/*用package语句指明所属包的名称,
* 相当于注释语句,只是告诉人说这些.java或.class在这个子目录下*/
package S.T;
public class C
{
public void sayPublic()
{
System.out.println("Hi,"+getClass()+ "."+ "public");
}
private void sayPrivate()
{
System.out.println("Hi,"+getClass()+ "."+ "private");
}
protected void sayProtected()
{
System.out.println("Hi,"+getClass()+ "."+ "protected");
}
void sayDefault()
{
System.out.println("Hi,"+getClass()+ "."+ "default");
}
}
D的源程序:
/*用package语句指明所属包的名称,
* 相当于注释语句,只是告诉人说这些.java或.class在这个子目录下*/
package S.T;
public class D
{
public void sayPublic()
{
System.out.println("Hi,"+getClass()+ "."+ "public");
}
private void sayPrivate()
{
System.out.println("Hi,"+getClass()+ "."+ "private");
}
protected void sayProtected()
{
System.out.println("Hi,"+getClass()+ "."+ "protected");
}
void sayDefault()
{
System.out.println("Hi,"+getClass()+ "."+ "default");
}
}
通过上面的实验,你可以得到什么结论:
结论是对于一个类(如A),如果不是在同一个包中,那其他的类(如Test1)如果不是A的子类,那么类Test1只能访问A的public修饰的方法,如果Test1是A的子类,那么它可以访问A的public和protected修饰的方法。也就是老师PPT上列出的:
由于时间比较紧,因为现在已经快12点了,得赶着睡觉然后明天早起写公选的读书报告了,所以对于这次实验就不在这里写详细的解析了,这里只复制下自己在做实验过程汇总整理的一些word笔记,通过这些笔记也基本可以搞清楚这次实验的相关知识和一些难点了:
1:这样编译C.java才能根据package语句自动新建子目录并在子目录生成.class文件(得先进入到lib文件夹路径里才有效),两种方法都行,第一种方法的”.”表示当前目录:
其他的A.java B.java D.java也是同样的方法。不用这种方法的话就无法根据package语句自动新建子目录并在子目录生成.class文件,而要自己新建目录并把.class文件剪切到该目录。
2:打包jar文件首先cd到lib文件夹再输入报告里面那句代码(”jar cvf E.jar *”):
3:一定要把C.java和C.class文件都放在子目录下,然后再生成jar包(对于A.java B.jaba不用压缩),然后再编译Test1.java才能通过。不然报下面这样的错误,为啥?
4:编译Test1.java:先cd到bin目录(即Test1.java所在目录),再javac,同时中间要加上引用的A类和B类的包的路径(最后的”;.”中的”.”表示把当前目录也就是bin目录也作为classpath纳入进来,虽然并没有用到这个目录的.class文件)
(这里的截图是把privated protected default的调用注释掉了之后的,没注释掉的应该是下面的截图,会报错)
5:运行Test1.class: 同样要加入classpath: