美文网首页
第八章、通用程序设计(二)

第八章、通用程序设计(二)

作者: Timorous | 来源:发表于2017-08-11 14:26 被阅读0次

    第五十二条、通过接口引用对象

    1. 如果有合适的接口类型存在,那么对于参数、返回值、变量和域来说,就都应该使用接口类型的声明。只有当你利用构造器创建某个对象的时候,才真正需要引用这个对象的类。如:List<Subscriber> subscribers = new Vector<Subscriber>();

    2. 如果养成了这个习惯,程序将更加灵活。当决定更换实现的时候,只需要改变构造器中类的名称。周围的代码都可以正常工作,对于这种变化并不在意。

    3. 如果没有合适的接口存在,完全可以用类而不是接口来引用对象。

      比如:值类(String和BigInteger)。值类很少会用多个实现编写,通常是final的,并且很少有对应的接口。

      第二种情形是:对象属于一个框架,而框架的基本类型就是类,如果对象属于这种基于类的框架,就应该使用相关的基类(往往是抽象类)来引用这个对象。

      最后一种情形是:类实现了接口,但是它提供了接口中不存在的额外方法。

    第五十三条、接口优先于反射机制

    1. 核心反射机制(core reflection facility)

      java.lang.reflect提供了“通过程序访问关于已装载的类的信息”的能力。给定一个Class实例,可以获得Constructor、Method和Field实例,分别代表该Class类所表示的类的Constructor、Method和Field。

      这些对象提供了“通过程序来访问类的成员名称、域类型、方法签名等信息”的能力

      而且,Constructor、Method、Field实例能够使你通过反射机制操作它们的底层对等体:通过调用上述三项上的方法,可以构造底层类的实例。调用底层类的方法,并访问底层类中的域。

      反射机制reflection允许一个类使用另一个类,即使当前者被编译时后者还不存在。

    2. 反射机制的代价:

      • 丧失了编译时类型检查的好处,包括异常检查。

      • 执行反射访问所需要的代码非常笨拙和冗长。

      • 性能损失:比普通方法要慢不少。

    3. 核心反射机制最初是为了基于组建的应用创建工具而设计的。这类工具需要根据装载类,并且用反射功能找出它们支持哪些方法和构造器。这些工具允许用户交互式地构造出访问这些类的应用程序,但是所产生出来的这些应用程序能够以正确的方式访问这些类,而不是以反射的方式。反射只是在设计的时候被用到。

    4. 通常,普通应用程序在运行时不应该以反射的方式访问对象。有一些复杂的应用程序需要使用反射机制。比如:类浏览器对象监视器代码分析工具解释型的内嵌式系统。在RPC(远程过程调用)系统中使用反射机制也是十分合适的。

    5. 反射机制的好处:

      对于有些程序,它们必须用到在编译时无法获取的类,但是在编译时存在适当的接口或者超类,通过它们可以引用这个类。以反射方式创建实例,然后通过它们的接口或者超类,正常的方式访问这些实例。Class.newInstance方法就已经提供不带参数的构造方法。

    6. 总结:反射机制是一种功能强大的机制,对于特定的复杂系统编程任务,它是非常必要的,但是它也有一些缺点。如有可能,就应该仅仅使用反射机制来实例化对象,而访问对象时使用编译时已知的某些接口或者超类。


    第五十四条、谨慎地使用本地方法

    1. Java Native Interface(JNI)允许Java应用调用本地方法Native Method,本地方法是指用本地程序设计语言(如C或C++)来编写特殊的方法。本地方法在本地语言中可以执行任意的计算任务,并返回到Java程序设计语言。

    2. 本地方法的用途:

      • 提供了”访问特定于平台的机制“的能力,比如访问注册表和文件锁。

      • 提供了访问遗留代码库的能力,从而可以访问遗留数据。

      • 本地方法可以通过本地语言,编写应用程序中注重性能的部分,以提高系统的性能。

    3. 使用本地方法来提高性能的方法不值得提倡:

      随着JVM实现变得越来越快。使用本地方法的缺点在于:由于本地语言不是安全的,会引发内存毁坏的错误;由于本地语言是与平台相关的,使用本地方法的应用程序不再是可自由移植的;使用本地方法的程序也更加难以调试。在进入和退出本地方法的时候需要相关固定的开销;胶合代码难以阅读


    第五十五条、谨慎地进行优化

    1. 三条关于优化的格言:

      • 很多计算上的过失都被归咎于效率(没有必要达到的效率)。而不是任何其他的原因——甚至包括盲目地做傻事。
      • 不要去计较效率上的一些小小得失,在97%的情况下,不成熟的优化才是一切问题的根源。
      • 在优化方面,我们应该遵守两条规则:
        • 不要进行优化,
        • 还是不要进行优化。
    2. 优化的弊大于利,尤其是不成熟的优化。这并不意味着,在完成程序之前就可以忽略性能问题,必须要在设计过程中考虑性能问题:努力避免那些限制性能的设计决策;要考虑API设计决策的性能后果。一旦谨慎地设计了程序,并且产生了一个清晰、简明、结构良好的实现,那么就到了考虑优化的时候了。


    第五十六条、遵守普遍接受的命名惯例

    1. java平台建立了一整套很好的命名惯例naming convention,不严格地说,这些命名惯例分为两大类:字面的(typographical)和语法的(grammatical)。

    2. 字面的惯例简要的介绍:

      • 包的名称应该是层次状的,用句号分割每个部分。每个部分都包括小写字母和数字(很少),任何将在你的组织之外使用的包,其名称都应该以你的组织的Internet域名开头,并且顶级域名放在前面,例如:edu.cmu,com.sun,gov.nsa标准类库和一些可选的包,其名称以java和javax开头,这属于这一规则的例外。用户创建的包的名称绝对不能以java和javax开头;

      • 包名称的剩余部分应该包括一个或者多个描述该包的组成部分。这些描述应该比较简短,一般不超过8个字符,鼓励使用有意义的缩写:如utilawt等。

      • 类和接口的名称,包括枚举和注解类型的名称,都应该包括一个或者多个单词,每个单词的首字母大写(如TimerTimerTask);应该尽量避免缩写。

      • 方法和域的名称与类和接口的名称一样,遵循相同的字面惯例,只是第一个字母应该小写。如果首字母缩写组成的单词是一个方法或者域名称的第一个单词,它就应该是小写形式。

      • ”常量域“它的名称应该包含一个或者多个大写的单词,中间用下划线符号隔开

      • 局部变量名称的字面惯例与成员名称类似,只不过它也允许缩写,单个字符和短字符序列的意义取决于上下文。

      • 参数类型名称通常由单个字母组成:通常是下面五种类型之一:T表示任意的类型E表示集合的元素类型K和V表示映射的键和值类型X表示异常。任何类型的序列都可以是T、U、V或者T1、T2、T3。

    3. 语法命名惯例:比字面惯例更加灵活但是有争议。

      • 类通常用一个名词或者名词短语命名;

      • 接口的命名与类类似,或者用一个已-able或者-ible结尾的形容词来命名:RunableIterable

      • 执行某个动作的方法通常用动词或者动词短语来命名,对于返回boolean值的方法,其名称往往以单词”is“开头,后面跟名词或者名词短语,或者任何具有形容词功能的单词或者短语:isEmptyisEnabled

      • 如果方法返回被调用对象的一个非boolean的函数或者属性,通常使用名词、名词短语或者以动词”get“开头的动词短语来命名:如size,hasCode或者getTime

      • 转换对象类型的方法、返回不同类型的独立对象的方法,通常称为toType;

      • 返回视图的方法通常称为asType:asList

      • 返回一个与被调用的对象同值的基本类型方法,通常被称为typeValue:intValue;

      • 静态工厂的常用名称为:valueOfofgetInstancenewInstancegetTypenewType

    相关文章

      网友评论

          本文标题:第八章、通用程序设计(二)

          本文链接:https://www.haomeiwen.com/subject/ojnlrxtx.html