zoukankan      html  css  js  c++  java
  • ThinkInJava4读书笔记之第五章隐藏实施过程

         用import 关键字导入一个完整的库时,就会获得“包”(Package)。例如:import java.util.*;它的作用是导入完整的实用工具(Utility)库,该库属于标准Java 开发工具包的一部分。由于Vector 位于java.util 里,所以现在要么指定完整名称“java.util.Vector”(可省略import 语句),要么简单地指定一个“Vector”(因为import 是默认的)。若想导入单独一个类,可在import 语句里指定那个类的名字:import java.util.Vector;

         为Java 创建一个源码文件的时候,它通常叫作一个“编辑单元”(有时也叫作“翻译单元”)。每个编译单元都必须有一个以.java 结尾的名字。而且在编译单元的内部,可以有一个公共(public)类,它必须拥有与文件相同的名字(包括大小写形式,但排除.java 文件扩展名)。如果不这样做,编译器就会报告出错。每个编译单元内都只能有一个public 类(同样地,否则编译器会报告出错)。那个编译单元剩下的类(如果有的话)可在那个包外面的世界面前隐藏起来,因为它们并非“公共”的(非public),而且它们由用于主public 类的“支撑”类组成。

        编译一个.java 文件时,我们会获得一个名字完全相同的输出文件;但对于.java 文件中的每个类,它们都有一个.class 扩展名。因此,我们最终从少量的.java 文件里有可能获得数量众多的.class 文件。

        “库”也由一系列类文件构成。每个文件都有一个public 类,所以每个文件都有一个组件。如果想将所有这些组件都归纳到一起,那么package 关键字就可以发挥作用。

    package mypackage;

         那么package 语句必须作为文件的第一个非注释语句出现。该语句的作用是指出这个编译单元属于名为mypackage 的一个库的一部分。根据Java 包(封装)的约定,名字内的所有字母都应小写。

        Java 解释器的工作程序如下:首先,它找到环境变量CLASSPATH(将Java 或者具有Java 解释能力的工具——如浏览器——安装到机器中时,通过操作系统进行设定)。CLASSPATH 包含了一个或多个目录,它们作为一种特殊的“根”使用,从这里展开对.class 文件的搜索。从那个根开始,解释器会寻找包名,并将每个点号(句点)替换成一个斜杠,从而生成从CLASSPATH 根开始的一个路径名(所以package foo.bar.baz 会变成foo\bar\baz 或者foo/bar/baz;具体是正斜杠还是反斜杠由操作系统决定)。随后将它们连接到一起,成为CLASSPATH 内的各个条目(入口)。以后搜索.class 文件时,就可从这些地方开始查找与准备创建的类名对应的名字。此外,它也会搜索一些标准目录——这些目录与Java 解释器驻留的地方有关。

         编译器遇到import 语句后,它会搜索由CLASSPATH 指定的目录,查找子目录,然后查找名称适当的已编译文件。

    自动编译

        为导入的类首次创建一个对象时(或者访问一个类的static 成员时),编译器会在适当的目录里寻找同名的.class 文件(所以如果创建类X 的一个对象,就应该是X.class)。若只发现X.class,它就是必须使用的那一个类。然而,如果它在相同的目录中还发现了一个X.java,编译器就会比较两个文件的日期标记。如果X.java 比X.class 新,就会自动编译X.java,生成一个最新的X.class。对于一个特定的类,或在与它同名的.java 文件中没有找到它,就会对那个类采取上述的处理。

    冲突

        若通过*导入了两个库,而且它们包括相同的名字,这时会出现什么情况呢?例如,假定一个程序使用了下述导入语句:

    import com.bruceeckel.util.*;

    import java.util.*;

         由于java.util.*也包含了一个Vector 类,所以这会造成潜在的冲突。然而,只要冲突并不真的发生,那么就不会产生任何问题——这当然是最理想的情况,因为否则的话,就需要进行大量编程工作,防范那些可能可能永远也不会发生的冲突。如现在试着生成一个Vector,就肯定会发生冲突。如下所示:

    Vector v = new Vector();

         它引用的到底是哪个Vector 类呢?编译器对这个问题没有答案。所以编译器会报告一个错误,强迫我们进行明确的说明。例如,假设我想使用标准的Java Vector,那么必须象下面这样编程:

    java.util.Vector v = new java.util.Vector();

         由于它(与CLASSPATH 一起)完整指定了那个Vector 的位置,所以不再需要import java.util.*语句,除非还想使用来自java.util 的其他东西。

    利用导入改变行为

        Java 已取消的一种特性是C 的“条件编译”,它允许我们改变参数,获得不同的行为同时不改变其他任何代码。Java 之所以抛弃了这一特性,可能是由于该特性经常在C 里用于解决跨平台问题:代码的不同部分根据具体的平台进行编译,否则不能在特定的平台上运行。由于Java 的设计思想是成为一种自动跨平台的语言,所以这种特性是没有必要的。

         然而,条件编译还有另一些非常有价值的用途。一种很常见的用途就是调试代码。调试特性可在开发过程中使用,但在发行的产品中却无此功能。Java的“断言机制”在调试过程中非常有用。jvm 断言默认是关闭的。要想让assert得部分运行的话,要使用 -ea 参数,否则包含assert得行会被忽略。assert表达式,assert exp1或assert exp1:exp2;assert详细参考:http://www.ibm.com/developerworks/cn/java/l-javaassertion/index.html

    类访问

         类文件中只能有一个public类,public类的名字必须与类文件名一致(包括大小写,不包括.java后缀),如果类文件中没有public类,类文件名可随意。不可将类设为privateprotected,只能为publicfriendly。若不愿其他人访问类,可将所有构造函数设为private这样一来,在类的一个static 成员内部,除自己之外的其他所有人都无法创建属于那个类的一个对象(单例模式就是这样)。

  • 相关阅读:
    典型相关性分析(刷题)
    轻音少女美图分享
    动漫美景
    linux下安装redis(全操作)
    前端限制对后端的请求频率
    idea自定义java方法的注释模板
    sql 语句,判断某个值在某个字段中是否存在,存在返回1,不存在返回0
    Error: Module not specified
    解决sql语句中DISTINCT和order by的冲突
    将后端传来的数据放入ul中
  • 原文地址:https://www.cnblogs.com/waimai/p/2952802.html
Copyright © 2011-2022 走看看