目录

[Java核心技术] package,import和classpath

Java 核心技术读书笔记——Java package,import和classpath

1 package和import

1.1 package

  • 所有的Java类都放置在同一个目录下,因此类之间的相互调用无显式声明调用。

    • 同一个目录下,两个类的名字不能相同
    • 文件过多,查找和修改都不易,且容易出错
  • Java支持多个目录放置Java,并且通过package/import/classpath/jar等机制配合使用,可以支持跨目录放置和特别调用Java类。

  • package包,类似于C++中的namespace

  • Java类文件的第一句话给出包的名称

    1
    2
    3
    4
    
    package cn.edu.zzu;
    public class PackageExample{
    
    }
    
  • 引用类的时候,必须采用全称引用;程序正文可以用短名称

  • PackageExample.java必须严格放置在cn/edu/zzu目录下

  • 包名尽量唯一,常用域名逆序

1.2 import

  • PackageExampleTest.java中,使用import关键字来引入PackageExample
  • 也可以采用import cn.edu.zzu.*;*代表这个目录下所有文件,但不包括子文件夹和子文件夹内的文件
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    // cn/edu/zzu/PackageExampleTest.java
    
    package cn.edu.zzu;
    public class PackageExample {
    
    }
    
    // cn/edu/zzu/PackageExampleTest.java
    package cn.edu.zzu;
    import cn.edu.zzu.PackageExample; 
    
    //如果PackageExample和当前类在同一个目录,可以省略上句import
    
    public class PackageExampleTest {
      public static void main(String[] args) {
        PackageExample obj = new PackageExample();
        //此处可以用类的短名称来引用
      }
    }
    
  • import规则
    • import必须全部放在package之后,类定义之前。
    • 多个import的顺序无关
    • 可以用*来引入一个目录下的所有类,比如import java.lang.*;,此意思是引入java.lang下面所有的类文件,但不包括java.lang下面所有的子目录文件,即并不包括java.lang.reflect.*;
    • import尽量精确,不推荐使用*,以免新增的同名程序会使得老程序报错,面临着调用类指代不清的风险
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// a/Main.java
package a;

public class Man {

}

// b/Main.java
package b;

public class Man {

}

// c/Main.java
package c;

import a.Man;

public class Test {

  public static void main(String[] args) {
    Man m = new Man();
    b.Man m2 = new b.Man();
  }

}

2 jar文件

  • jar文件,一种扩展名为jar的文件,是Java所特有的一种文件格式,用于可执行文件的传播。
  • jar文件实际上是一组class文件的压缩包
  • 项目中引入一个jar文件,就可以使用jar文件中所有类(.class文件),无需类的源码(.java文件)。

2.1 jar文件优势

  • jar文件可以包括多个class,比多层目录更加中、简洁实用
  • jar文件经过压缩,只有一个文件,在网络下载和传播方面,更具有优势
  • jar文件只包括class,没有包含java文件,在保护源码文件知识版权方面,能够起到更好的作用
  • 将多个class文件压缩成jar文件,可以规定给一个版本号,更容易进行版本控制

2.2 命令行

  • 手动在c:\temp创建cn.com.test.Man.java

2.2.1 编译

1
javac c:\temp\cn\com\test\Man.java

2.2.2 运行

  • java -classpath .;c:\temp cn.com.test.Man
    1
    
    java -cp .;c:temp cn.com.test.Man
    
  • 第一部分:java,执行命令,是java.exe的简写。
  • 第二部分:-classpath 固定格式参数,可以简写成-cp
  • 第三部分: 是一个(Windows分号,Linux/Mac冒号连接起来的)字符串。按分隔符隔开,得到一个个子路径。
  • 第四部分:主执行类的全称(含包名)

2.2.3 编译和运行规则

  • 编译一个类,需要java文件的全路径,包括扩展名。
  • 运行一个类,需写类名全称(非文件路径),无须写扩展名。
  • 编译类的时候,需要给出这个类的所有依赖(包括依赖的类再次依赖的所有其他类)所在路径。
  • 运行类的时候,需要给出这个类,以及被依赖类的路径总和。
  • classpath参数也可以包含jar包。如果路径内有空格,请将classpath参数整体加双引号。
  • classpath写在前面优先级更高。
    1
    
    java -classpath ".;c:\test.jar;c:\temp;c:\a bc" cn.com.test.Man
    
  • Java运行时会将classpath按照分隔符裁开,在每个子路径下一次寻找所需要的类。如果子路径是jar文件,那就将jar临时解压,在里面寻找。

3 Java访问权限

3.1 四种访问权限

  • private:私有的,只能本类访问
  • default:(通常忽略不写):同一个包内访问
  • protected:同一个包,子类均可访问
  • public:公开的,所有类都可以访问
同一个类 同一个包 不同包的子类 不同包的非子类
private
default
protected
public

3.2 使用范围

  • 四种都可以用来修饰成员变量、成员方法、构造函数
  • defaultpublic可以修饰类
  • 建议成员变量都是private
  • 建议成员方法都是public

3.3 实例

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

/* test1/A.java */
package test1;

public class A {
  private int v1 = 1;
  int v2 = 2;
  protected int v3 = 3;
  public int v4 = 4;
  
  private void showV1() 
  {
    System.out.println(v1);
  }
  void showV2()
  {
    System.out.println(v2);
  }
  protected void showV3()
  {
    System.out.println(v3);
  }
  public void showV4()
  {
    System.out.println(v4);
  }
}

/* test1/B.java */

package test1;

//B and A are in the same package
public class B {
  public void show()
  {
    //B is not subclass of A
//    System.out.println(v1);  //error
//    System.out.println(v2);  //error
//    System.out.println(v3);  //error
//    System.out.println(v4);  //error    
//    showV1();   //error
//    showV2();   //error
//    showV3();   //error
//    showV4();   //error
    
    A obj = new A();
    //System.out.println(obj.v1);   error,  private
    System.out.println(obj.v2);
    System.out.println(obj.v3);
    System.out.println(obj.v4);
    
    //obj.showV1();   error,  private
    obj.showV2();
    obj.showV3();
    obj.showV4();
  }
}

/* test1/C.java */

package test1;

//C is a subclass of A, and in the same package of A.
public class C extends A {
  public void show()
  {   
    //System.out.println(v1);  error, private
    System.out.println(v2);
    System.out.println(v3);
    System.out.println(v4);   
    //showV1();  error, private
    showV2();
    showV3();
    showV4();
    
    A obj = new A();
    //System.out.println(obj.v1);   error,  private
    System.out.println(obj.v2);
    System.out.println(obj.v3);
    System.out.println(obj.v4);
    
    //obj.showV1();   error,  private
    obj.showV2();
    obj.showV3();
    obj.showV4();
  }
}

/* test2/D.java */

package test2;

import test1.A;

public class D extends A{
  public void show()
  {   
    //System.out.println(v1);  error, private
    //System.out.println(v2);  error, default
    System.out.println(v3);
    System.out.println(v4);   
    //showV1();  error, private
    //showV2();  error, default
    showV3();
    showV4();
    
    A obj = new A();
    //System.out.println(obj.v1);   error,  private
    //System.out.println(obj.v2);   error,  default
    //System.out.println(obj.v3);   error,  protected 只能作为子类才能访问   
    System.out.println(obj.v4);
    
    //obj.showV1();   error,  private
    //obj.showV2();   error,  default
    //obj.showV3();   error   protected 只能作为子类才能访问
    obj.showV4();
  }
}

/* test2/E.java */

package test2;

import test1.A;

public class E {
  public void show()
  {   
    //E is not a subclass of A. And E is not in the same package of A.
    //System.out.println(v1);  error, private
    //System.out.println(v2);  error, default
    //System.out.println(v3);
    //System.out.println(v4);   
    //showV1();  error, private
    //showV2();  error, default
    //showV3();
    //showV4();
    
    A obj = new A();
    //System.out.println(obj.v1);   error,  private
    //System.out.println(obj.v2);   error,  default
    //System.out.println(obj.v3);   error,  protected 只能作为子类才能访问   
    System.out.println(obj.v4);
    
    //obj.showV1();   error,  private
    //obj.showV2();   error,  default
    //obj.showV3();   error   protected 只能作为子类才能访问
    obj.showV4();
  }
}