第八章、包及访问控制权限
8-1、包的定义及导入
package 是在使用多个类或接口时,为了避免名称重复而采用的一种措施,直接在程序中加入package关键字即可。包的定义格式:
package 包名称 . 子包名称; |
package org.lxh.demo08 ; // 定义一个包 class Demo{ public String getInfo(){ return “Hello World!!!” ; } }; public class PackageDemo01{ public static void main(String args[]){ System.out.println(new Demo().getInfo()); } }; |
一个包其实就是一个文件夹,定义包之后,会生成一个名为org的文件夹,里面就有两个类文件。执行程序打包命令:
javac –d . PackageDemo01. JAVA |
程序编译完成后会生成一个名为org的文件夹,里面会生成一个Demo.class和PackageDemo01.class的两个类文件。生成完*.class之后就可以直接访问了:
java org.lxh.demo08.PackageDemo01 |
8-2、包的导入
当一个包的 class文件 需要使用另外一个包的class文件的时候就需要使用导入指令。在之前的程序中,两个类是存放在一个包中的,因此代码与之前没有什么根本的不同,但是如果几个类存放在不同的包中,则在使用类的时候就必须通过import语句导入。
语法:
· import 包名称 . 子包名称 . 类名称; 手工导入所需要的类
·import 包名称 . 子包名称 . *; 由JVM自动加载所需要的类
Demo.java:
package org.lxh.demo08.c ; public class Demo{ public String getContent(){ return “MLDN LXH” ; } }; |
ImportDemo01.java:
package org.lxh.demo08.b ; // 放在不同的包中 import org.lxh.demo08.a.* ; // 导入不同包中的Demo类 public class ImportDemo01{ public static void main(String args[]){ System.out.println(new Demo().getContent ()) ; } }; |
编译的时候应该先编译Demo.java类,之后再编译ImportDemo01.java,因为后者使用了前者的类进行操作。
编译ImportDemo01.java的时候出现了以下的错误提示:
ImportDemo01.java:2: 错误: 程序包org.lxh.demo08.a不存在 import org.lxh.demo08.a.* ; // 导入不同包中的Demo类 ^ ImportDemo01.java:5: 错误: 找不到符号 System.out.println(new Demo().getInfo()) ; ^ 符号: 类 Demo 位置: 类 ImportDemo01 2 个错误 |
也就是说Demo类如果需要被外包访问的时候需要定义成public class,修改Demo类:
package org.lxh.demo08.a; public class Demo{ public String getContent (){ return “Hello World!!!”; } } |
关于public class与class声明类:
如果一个类声明为public class则文件名称必须与类名称一致,而且在一个类中只能有一个public class,而如果使用class声明一个类,则文件名称可以与类名称不一致,但是执行的时候必须执行生成的class文件名称。除了这些之外,public class和class还在包的访问上有所限制,如果一个类只在本包中访问,不需要被外包访问,则直接声明成class即可,而如果一个类需要被外包访问,则必须声明为public class。
以上的操作是明确的使用了包 . 类名称的方式导入的,如果现在假设要导入一个包中的很多类,这样写肯定很麻烦,我们可以直接使用“*”的方式进行导入:
package org.lxh.demo08.b ; // 放在不同的包中 import org.lxh.demo08.a.* ; // 导入不同包中的Demo类 public class ImportDemo01{ public static void main(String args[]){ System.out.println(new Demo().getInfo()) ; } }; |
上面两种导入语句哪种性能更高呢?
·第一种:import org.lxh.demo08.a.Demo;
·第二种:import org.lxh.demo08.a.*;
实际上这两种的性能都是一样的,因为如果使用后者,是由 JVM 帮助用户判定需要导入的类,不需要的类,是不会被加载进来的。
但是在导包的时候也需要注意另外一个问题,如果现在导入了不同包的同名类的时候,则就有可能出现不明确的错误信息。
package org.lxh.demo08.c ; public class Demo{ public String getContent(){ return “MLDN LXH” ; } }; |
现在在org.lxh.demo08.a中有一个Demo类,在org.lxh.demo08.b中也有一个Demo类,之后定义一个类,需要同时导入a 和 c的包。
package org.lxh.demo08.d ; import org.lxh.demo08.a.* ; // 包中存在Demo类 import org.lxh.demo08.c.* ; // 包中存在Demo类 public class ImportDemo02{ public static void main(String args[]){ Demo d = new Demo() ; System.out.println(d.getContent ()) ; } }; |
编译出错:
ImportDemo02.java:6: 错误: 对Demo的引用不明确, org.lxh.demo08.c中的类 org.lxh.demo08.c.Demo和org.lxh.demo08.a中的类 org.lxh.demo08.a.Demo都匹配 Demo d = new Demo() ; ^ ImportDemo02.java:6: 错误: 对Demo的引用不明确, org.lxh.demo08.c中的类 org.lxh.demo08.c.Demo和org.lxh.demo08.a中的类 org.lxh.demo08.a.Demo都匹配 Demo d = new Demo() ; ^ 2 个错误 |
所以此时,如果出现这样情况的话,则最好写入完整的“包 . 类名称”。
修改代码:
package org.lxh.demo08.d ; import org.lxh.demo08.a.* ; // 包中存在Demo类 import org.lxh.demo08.c.* ; // 包中存在Demo类 public class ImportDemo02{ public static void main(String args[]){ org.lxh.demo08.a.Demo d = new org.lxh.demo08.a.Demo () ; System.out.println(d.getContent ()) ; } }; |
|
8-3、系统常见包
| 名称 | 作用 |
1 | java.lang | 此包为基本包,像String这样的类就都保存在此包之中,在JDK1.0的时候如果想编写程序,则必须手工导入此包,但是随后的 JDK 解决了此问题,所以此包现在为自动导入。 |
2 | java.lang.reflect | 此包为 反射机制 的包,是 java .lang的子包,在JAVA常用类库中会介绍。 |
3 | java.util | 此包为工具包,一些常用的 类库 、日期操作等都在此包中。 |
4 | java.text | 提供了一些文本的处理类库 |
5 | java.sql | 数据库操作包,提供了各种数据库操作的类和接口。 |
6 | java.net | 完成网络编程 |
7 | java.io | 输入、输出处理 |
8 | java. awt | 包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI) |
9 | javax.swing | 此包用于建立图形用户界面,此包中的组件相对于java.awt包而言是轻量级组件 |
8-4、静态导入
如果一个类中的方法全部是使用static声明的 静态方法 ,则在导入的时候就可以直接使用“import static”的方式导入,导入的格式如下:
import static 包 . 类 . *;
package org.lxh.demo08.e ; public class Operate{ // 里面的方法全部都是static类型 public static int add(int i,int j) { // 加法操作 return i + j ; } public static int sub(int i,int j) { // 减法操作 return i – j ; } public static int mul(int i,int j) { // 乘法操作 return i * j ; } public static int div(int i,int j) { // 除法操作 return i / j ; } }; |
如果按之前的import导入的话,则调用的时候肯定使用的是类 . 方法()。
package org.lxh.demo08.f ; import static org.lxh.demo08.e.Operate.* ; // 静态导入 public class StaticImportDemo{ public static void main(String args[]){ System.out.println(“3 + 3 = ” + add(3,3)) ; // 直接调用静态方法 System.out.println(“3 – 2 = ” + sub(3,2)) ; // 直接调用静态方法 System.out.println(“3 * 3 = ” + mul(3,3)) ; // 直接调用静态方法 System.out.println(“3 / 3 = ” + div(3,3)) ; // 直接调用静态方法 } }; |
8-5、 JAR 命令
当开发者为客户开发出了一套JAVA类之后,肯定要把这些类交给用户使用,但是如果所有的类是直接通过*.class的格式给用户,则会比较麻烦,所以一般情况下会将这些*.class文件压缩成一个文件交付给客户使用,那么这样的文件就称为jar文件(Java Archive File ),如果要想生成jar文件,直接使用JDK中bin目录里的jar.exe就可以将所有的类文件进行压缩。
JAR命令中的主要参数:
· “C”:创建新的文档
· “V”:生成详细的输出信息
· “F”:指定存档的文件名
用法: jar {ctxui}[vfm0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files … 选项包括: -c 创建新的归档文件 -t 列出归档目录 -x 从档案中提取指定的 (或所有) 文件 -u 更新现有的归档文件 -v 在标准输出中生成详细输出 -f 指定归档文件名 -m 包含指定清单文件中的清单信息 -e 为捆绑到可执行 jar 文件的独立应用程序 指定应用程序入口点 -0 仅存储; 不使用情况任何 ZIP 压缩 -M 不创建条目的清单文件 -i 为指定的 jar 文件生成索引信息 -C 更改为指定的目录并包含其中的文件 如果有任何目录文件, 则对其进行递归处理。 清单文件名, 归档文件名和入口点名称的指定顺序 与 ‘m’, ‘f’ 和 ‘e’ 标记的指定顺序相同。 示例 1: 将两个类文件归档到一个名为 classes.jar 的归档文件中: jar cvf classes.jar Foo.class Bar.class 示例 2: 使用现有的清单文件 ‘mymanifest’ 并 将 foo/ 目录中的所有文件归档到 ‘classes.jar’ 中: jar cvfm classes.jar mymanifest -C foo/。 |
例:
package org.lxh.demo08.demo ; public class Hello{ public String getInfo(){ return “Hello World!!!” ; } }; |
将其打包编译:javac –d . Hello.java
将其打成jar包:jar –cvf my.jar org
已添加清单 正在添加: org/(输入 = 0) (输出 = 0)(存储了 0%) 正在添加: org/lxh/(输入 = 0) (输出 = 0)(存储了 0%) 正在添加: org/lxh/demo08/(输入 = 0) (输出 = 0)(存储了 0%) 正在添加: org/lxh/demo08/Demo.class(输入 = 300) (输出 = 237)(压缩了 21%) 正在添加: org/lxh/demo08/PackageDemo01.class(输入 = 510) (输出 = 332)(压缩了 34% ) 正在添加: org/lxh/demo08/c/(输入 = 0) (输出 = 0)(存储了 0%) 正在添加: org/lxh/demo08/c/Demo.class(输入 = 290) (输出 = 229)(压缩了 21%) 正在添加: org/lxh/demo08/a/(输入 = 0) (输出 = 0)(存储了 0%) 正在添加: org/lxh/demo08/a/Demo.class(输入 = 290) (输出 = 229)(压缩了 21%) 正在添加: org/lxh/demo08/d/(输入 = 0) (输出 = 0)(存储了 0%) 正在添加: org/lxh/demo08/d/ImportDemo02.class(输入 = 521) (输出 = 341)(压缩了 34 %) |
一个jar包如果要想使用的话,则必须配置 classpath 路径。
set classpath=;F:\网页\李兴华\020801_【第8章:包及访问控制权限】_包的定义及导入\代码\my.jar |
例:
package org.lxh.demo08 ; import org.lxh.demo08.demo.Hello ; public class ImportJarDemo{ public static void main(String args[]){ Hello hello = new Hello() ; System.out.println(hello.getInfo()) ; } }; |
8-6、 访问控制 权限及命名规范
8-6-1、访问控制权限
Java中存在四种访问权限:
· private 访问权限
·default(默认)访问权限
· Protected 访问权限
·public访问权限
范围 | private | default | protected | public |
同一类 | √ | √ | √ | √ |
同一包中的类 |
| √ | √ | √ |
不同包的子类 |
|
| √ | √ |
其他包中的类 |
|
|
| √ |
private:可以定义方法,属性,定义的方法和属性不能被类的外部所看到。
default:可以在本包中的任意地方访问。
protected :保护,不同包的非子类不可以访问。
public:公共的,都可以访问,不受任何的限制。
package org.lxh.demo08.g ; public class HelloDemo{ protected String name = “LXH” ; // 只能在本包及不同包的子类中访问 }; |
在其他包中访问此类中的属性。
package org.lxh.demo08.h ; import org.lxh.demo08.g.HelloDemo ; class SubHelloDemo extends HelloDemo{ public void print(){ System.out.println(“访问受保护属性:” + super.name) ; } }; public class ProtectedDemo01{ public static void main(String args[]){ SubHelloDemo sub = new SubHelloDemo() ; sub.print() ; } }; |
如果现在没有使用子类,而是直接在不同类中访问,则会出现无法访问的错误。
package org.lxh.demo08.h ; import org.lxh.demo08.g.HelloDemo ; public class ProtectedDemo02{ public static void main(String args[]){ HelloDemo sub = new HelloDemo() ; System.out.println(sub.name) ; // 错误的,不同包的类无法访问 } }; |
编译时出现下面的错误提示信息:
ProtectedDemo02.java:6: 错误: name可以在HelloDemo中访问protected System.out.println(sub.name) ; // 错误的,不同包的类无法访问 ^ 1 个错误 |
当产生了一个类之后,为了保证类中的内容不被外部直接看到,则使用private关键字。
但是,如果现在两个有关系的类要进行属性互相访问的话就比较麻烦,之前只能使用getter/setter取得和设置,所以为了减少私有属性的访问的麻烦,使用了内部类,但是内部类本身会破坏程序的结构。
为了让一个类的内容可以继续方便的时候访问,使用了继承的概念,但是在继承中private属性也是无法被子类看到的,所以此时,为了方便子类的操作,可以将属性使用protected进行封装,这样一来外部也无法直接看到(不同包)。
既然有了继承的关系,就可以使用向上或向下的转型操作,以完成多态性,但是在开发中类与类之间的直接继承并不多见,而往往继承抽象类或实现接口,当若干个操作间需要 耦合 的时候就可以使用接口完成。
既然有内部类,则如果一个接口或抽象类的子类只使用了次,则可以将其定义成匿名内部类。
开发中没有包的类是绝对不存在的。
封装 继承 多态.
8-6-2、java的命名规范
在JAVA中,声明类、方法、属性等都是有一定的规范的,此规范如下所示:
·类:所有单词的首字母大写,如:TestJava
·方法:第一个单词的首字母小写,之后每个单词的首字母大写,如:getInfo();
·属性:第一个单词的首字母小写,之后每个单词的首字母大写,如:studentName
·包:所有单词的字母小写,如:org.lxh.demo
·常量:所有单词的字母大写,如:FLAG