java的封装
包的概念:
包内含一组类,他们被组织再一个独立的命名空间下
可以通过import进行引入使用
格式import java.util.* 或者import java.util.ArrayList
作用:提供一种管理命名空间的机制。所有类名之间都是互相隔离的,类A中的f()方法不会和类B中的f()方法冲突。
编译单元:一个java源代码文件。
注意:一个编译单元只能有一个公共类,而且类名必须和文件名相同。
代码组织
当编译一个 .java 文件时,.java 文件的每个类都会有一个输出文件。每个输出的文件名和 .java 文件中每个类的类名相同,
只是后缀名是 .class。因此,在编译少量的 .java 文件后,会得到大量的 .class 文件
java的编译方式:
在 Java 中,可运行程序是一组 .class 文件,它们可以打包压缩成一个 Java 文档文件(JAR,使用 jar 文档生成器)
Java 解释器负责查找、加载和解释这些文件。
类库:
类库是一组类文件。每个源文件通常都含有一个 public 类和任意数量的非 public 类,因此每个文件都有一个 public
组件。如果把这些组件集中在一起,就需要使用关键字 package。
使用package语句(一般默认自己添加)它必须是文件中除了注释之外的第一行代码。
package hiding; 意味着这个编译单元是一个名为 hiding 类库的一部分。换句话说,你正在声明的编译单元中的 public 类名称位于名
为 hiding 的保护伞下。任何人想要使用该名称,必须指明完整的类名或者使用 import 关键字导入 hiding 。
包名:
按照惯例,package 名称是类的创建者的反顺序的 Internet 域名。如果你遵循惯例,因为 Internet 域名是独一无二的
所以你的 package 名称也应该是独一无二的,不会发生名称冲突。
遇到冲突:
以导入单个类以防冲突——只要不在同一个程序中使用有冲突的名字(若使用了有冲突的名字,必须明确指明全名)。
编译过的代码通常位于与源代码的不同目录中。这是很多工程的标准,而且集成开发环境(IDE)通常会自动为我们做这些。必须保证 JVM 通过 CLASSPATH 能找到编译后的代码。
访问权限修饰符
java默认的权限是"包访问权限"
Java 访问权限修饰符 public,protected 和 private 位于定义的类名,属性名和方法名之前。每个访问权限修饰符只能控制它所修饰的对象。
包访问权限
默认访问权限没有关键字,通常被称为包访问权限(package access)(有时也称为 friendly)。 这意味着当前包中的所有其他类都可以访问那个成员。对于这个包之外的类,这个成员看上去是 private 的。 通过包访问权限,位于同一编译单元中的所有类彼此之间都是可访问的。
取得对成员的访问权的唯一方式是:
使成员成为 public。那么无论是谁,无论在哪,都可以访问它。 予成员默认包访问权限,不用加任何访问修饰符,然后将其他类放在相同的包内。这样,其他类就可以访问该成员。 继承的类既可以访问 public 成员,也可以访问 protected 成员(但不能访问 private 成员)。只有当两个类处于
同一个包内,它才可以访问包访问权限的成员。 提供访问器(accessor)和修改器(mutator)方法(有时也称为"get/set" 方法),从而读取和改变值。
public: 接口访问权限
紧随 public 后声明的成员对于每个人都是可用
private: 你无法访问
意味着除了包含该成员的类,其他任何类都无法访问这个成员。同一包中的其他类无法访问 private 成员,因此这等于说是自己隔离自己。
默认的包访问权限通常提供了足够的隐藏措施;记住,使用类的客户端程序员无法访问包访问权限成员。
因此,通常考虑的是把哪些成员声明成 public 供客户端程序员使用
protected: 继承访问权限
基类的创建者会希望某个特定成员能被继承类访问,但不能被其他类访问。这时就需要使用 protected。protected 也提供包访问权限,也就是说,相同包内的其他类可以访问 protected 元素。
作用:
访问控制在数据类型内部划定了边界。第一个原因是确立客户端程序员可以使用和不能使用的边界。可以在结构中建立自己的
内部机制而不必担心客户端程序员偶尔将内部实现作为他们可以使用的接口的一部分。 二个原因:将接口与实现分离。如果在一组程序中使用接口,而客户端程序员只能向 public 接口发送消息的话,那么就可以
自由地修改任何不是 public 的事物(例如包访问权限,protected,或 private 修饰的事物),却不会破坏客户端代码。 采用一种创建类的风格: public 成员放在类的开头, 接着是 protected 成员, 包访问权限成员, 最后是 private 成员。 这么做的好处是类的使用者可以从头读起,首先会看到对他们而言最重要的部分(public 成员,因为可以从文件外访问它们)
,直到遇到非 public 成员时停止阅读
接口和实现
访问控制通常被称为隐藏实现(implementation hiding)。
将数据和方法包装进类中并把具体实现隐藏被称作是封装(encapsulation)。
public class OrganizedByAccess { public void pub1() {/* ... */} public void pub2() {/* ... */} public void pub3() {/* ... */} private void priv1() {/* ... */} private void priv2() {/* ... */} private void priv3() {/* ... */} private int i; // ... }
这么做只能是程序阅读起来稍微容易一些,因为实现和接口还是混合在一起。也就是说,你仍然能看到源代码——实现部分,因为它就在类中。将接口展现给类的使用者实际上是类浏览器的任务,类浏览器会展示所有可用的类,并告诉你如何使用它们(比如说哪些成员可用)
类访问权限
访问权限修饰符也可以用于确定类库中的哪些类对于类库的使用者是可用的。如果希望某个类可以被客户端程序员使用,就把关键字 public 作用于整个类的定义。这甚至控制着客户端程序员能否创建类的对象。
格式:
为了控制一个类的访问权限,修饰符必须出现在关键字 class 之前: public class Widget
限制
每个编译单元(即每个文件)中只能有一个 public 类。这表示,每个编译单元有一个公共的接口用 public 类表示。
该接口可以包含许多支持包访问权限的类。一旦一个编译单元中出现一个以上的 public 类,编译就会报错。 public 类的名称必须与含有该编译单元的文件名相同,包括大小写。所以对于 Widget 来说,文件名必须是
Widget.java,不能是 widget.java 或 WIDGET.java。再次强调,如果名字不匹配,编译器会报错。
注意;类既不能是 private 的(这样除了该类自身,任何类都不能访问它),也不能是 protected 的。所以对于类的访问权限只有两种选择:包访问权限或者 public。
为了防止类被外界访问,可以将所有的构造器声明为 private,这样只有你自己能创建对象(在类的 static 成员中)
// hiding/Lunch.java // Demonstrates class access specifiers. Make a class // effectively private with private constructors: class Soup1 { private Soup1() {} public static Soup1 makeSoup() { // [1] return new Soup1(); } } class Soup2 { private Soup2() {} private static Soup2 ps1 = new Soup2(); // [2] public static Soup2 access() { return ps1; } public void f() {} } // Only one public class allowed per file: public class Lunch { void testPrivate() { // Can't do this! Private constructor: //- Soup1 soup = new Soup1(); } void testStatic() { Soup1 soup = Soup1.makeSoup(); } void testSingleton() { Soup2.access().f(); } }
将构造函数修饰为private
soup1 通过 static 方法创建对象或者
soup2先创建一个静态对象,当用户需要访问它时返回对象的引用即可。
Soup2 用到了所谓的设计模式(design pattern)。这种模式叫做单例模式(singleton),因为它只允许创建类的
一个对象。Soup2 类的对象是作为 Soup2 的 static private 成员而创建的,所以有且只有一个,你只能
通过 public 修饰的 access() 方法访问到这个对象。