Java技术基础——Java编程思想学习小节(二)

来源:互联网 发布:域名黑名单查询 编辑:程序博客网 时间:2024/04/30 12:40

Java编程思想学习小节(二)

前言:由于最近在找工作,将《Java编程思想》这一经典书籍翻阅一番,回顾其中关键和精彩之处总结出来做个记录,并查阅相关资料进行扩展,供日后参考。如有理解错误,请不吝赐教。(从该书第5章开始)

第六章 访问权限控制、第七章 复用类

1. 编译单元

一个Java源代码文件称为一个编译单元,每个编译单元只允许有一个public类,否则编译报错。编译单元中的其他类在包外是不可见的,它们主要用来为public类提供支持。

Java可运行程序是一组可以打包并压缩为一个Java文档文件(JAR)的.class文件。

使用package语句必须是文件中除了注释以外的第一句程序代码,表示该编译单元是声明类库的一部分。

Java解释器的运行过程如下:首先找出环境变量CLASSPATH,它可以包含一个或多个目录,用作查找.class文件的根目录。从根目录开始,获取包的名称并将每个句点替换成反斜杠,以从CLASSPATH根中产生一个路径名称。接着就在该目录中查找.class文件。如,CLASSPATH设置为:CLASSPATH=.;D:\path\Java;,类所在的包为jay.tal.ent,那么解释器生成的查找路径为:D:\path\Java\jay\tal\ent。

使用import static语句可以直接使用包中类所有的静态方法。

Java中没有类似C中条件编译的功能,条件编译可以用来调试。Java中的替代方法是:将调试和非调试类代码定义在不同的包中,开发时导入调试包,发布时导入非调试包即可。

编译过的代码通常放置在与源代码的不同目录中,但是必须保证JVM使用CLASSPATH可以找到该路径。


2. 访问权限修饰词

包访问权限允许将包内所有相关的类组合起来,使它们彼此之间可以相互作用。没有任何关键字。若一个成员是包访问权限,那么包内其他类可以访问该成员。

protected也提供包访问权限,即相同包内的其他类可以访问protected元素。

public类的名称必须完全与含有该编译单元的文件名相匹配,包括大小写。

其实编译单元内可以完全不带public类,可以随意对文件命名,但是这并不常用。

除了内部类以外,类既不可以是private的也不可以是protected的。仅有两个选择:public和包访问权限。


3. 组合与继承

编译器不是给每个引用都创建默认对象的目的是减小不必要的负担。

一个文件中的每个类都设置一个main方法,可使每个类的单元测试变得简便易行。只有命令行所调用的那个类的main方法会被执行,无论该类是public的还是有包访问权限的。可以在一个类的main方法中国明确调用另一个类的main方法。

如果不提供super关键字,无法调用基类的方法,因为直接调用会产生递归。

当创建了一个派生类(也叫导出类)对象时,该对象就包含了一个基类子对象。这个子对象被包装在派生类的内部。

构造过程是由基类向外扩散的。Java会自动在派生类的构造器中插入对基类构造器的调用,前提是基类构造器是无参的。如果有参数,那么就要在派生类的构造器中使用super关键字显式调用基类构造器,否则编译器会去寻找默认构造器,发现找不到就会报错。另外,调用基类构造器必须是派生类构造器中的第一件事,否则编译器也会报错。

代理也是一种实现类复用的方式,它是继承与组合的中庸之道,Java没有直接支持。思想是:通过组合持有一个对象,然后提供自己的接口调用对象能提供的接口,相当于一次间接调用。这样在实际的调用前可以做一个预处理操作。另一个好处是,如果使用继承获得接口就获得全部接口,而代理可以选择性地提供部分接口,相当于将所有接口隐藏在持有的对象中了。

在Java中,在派生类中引入新的重载方法后,基类的重载方法仍是可用的,这一点与C++不同。如果函数签名完全与基类相同,那么就是覆盖方法,这在C++中是不允许的。这时可以使用Override注解也可以不使用,其实这个注解的作用是当你不想重载(想重写)而意外重载时,编译器会报错提示。

组合技术通常用于想在新类中使用现有类的功能而非它的接口这种情形。在继承的时候,使用某个现有类,开发一个它的特殊版本。

如果需要一个protected成员变量,通常将其声明为private,并将访问它的方法声明为protected。

到底使用组合还是继承,一个最清晰的判断办法就是问一问自己是否需要从新类向基类进行向上转型。如果需要,则继承是必要的。


4. final关键字

final数据通常用于基本数据类型,一个既是static又是final的域只占据一段不能改变的存储空间。对引用对象使用final只能使对象引用恒定不变,不能使对象的值不变。对数组也是一样,final数组元素值是可以改变的。

final域可以不在声明的时候初始化,但必须在构造器中初始化。

final参数可以读取,但却无法修改参数。这一特性主要用来向匿名内部类传递数据。

final用于方法保证方法在继承时不被覆盖。其实每个private方法都是隐式final的,因为private方法显然无法被覆盖。因此,如果在private方法上加final,编译器不会报错,但也没什么意义。

final用于类表示该类不能被继承,因此final类中所有方法都隐式是final的。


5. 加载

类的代码只有在初次使用时被加载,这发生在类在其任何static被访问时,构造器也是一种静态成员。如果发现一个类有基类,则加载它的基类,一层一层向上加载。然后根基类的static成员初始化,然后是下一个派生类,从上至下依次进行。执行构造器时,首先追溯到根基类,初始化其数据成员,并执行构造器,一层一层向下进行,到当前类的构造器。