目标:
1.1 编写代码,声明类(包括抽象类和各种形式的嵌套类) 、接口和枚举。编写代码,包含包和导入语句(包括静态导入)的恰当使用。
1.3.1 源文件生命规则
在深入研究类声明之前, 首先简要回顾一下与源文件中的声明类、import语句和package语句相关的规则:
1)每个源代码文件只能有一个public类。
2)注释可以出现在源代码文件中任一行的开始或结尾处,它们与本书介绍的任何定位规则不相关。
3)如果文件中有一个public类,那么文件名必须与public类的名称匹配。例如,声明为public class Dog{}的类必须位于名为Dog.java的源代码中。
4)如果类是包的一部分,那么package语句必须位于源代码文件的第一行,并且出现在任何import语句之前。
5.1)如果有import语句,则他们必须位于package语句(如果有)和类声明之间;
5.2)如果没有package语句,那么import语句必须位于源代码文件中的第一行或最前的几行;
5.3) 如果没有package语句或import语句,那么类声明必须位于源代码文件中的第一行。
6) import语句和pacakage语句使用与源代码文件中的所有类。换句话说,不可能在一个文件中声明多个类并使他们位于不同的包中,或者使用不同的导入语句。
7)一个文件可以具有多个非公共类。
8)不包含公共类的文件可以具有与该文件汇总的任何类都不匹配的名称。
1.3.2类声明和修饰符
下面的代码是一个“裸” 类声明:
class MyClass{ }
该代码能很好地通过编译,但也可以在类声明前添加修饰符。
修饰符分为以下两类。
1)访问修饰符:public 、protected和private。
2)非访问修饰符(包括strictf、final和abstract)
Java中的访问控制需要一些技巧,因为它有4种访问控制(访问级别) ,但只有3个访问修饰符。第4个访问控制级别(称为默认访问级别或包级访问级别)是指当不使用3种访问修饰符中的任何一种时所得到的访问控制。换句话说,无论是否显示地键入,声明的每个类、方法和实例变量都有一种访问控制。尽管4种访问控制都是用于多数方法和变量声明,但是,声明类时只能使用public或默认访问,另外两种访问控制级别对类没有任何意义,后面将会看到这一点。
类访问
访问类意味着什么呢?当我们说来自一个类(类 A)的代码可以访问另一个类(类B)时,就意味着类A能够执行以下3种操作之一:
1)创建类B的一个实例(instance) 。
2)扩展(extends)类B(换句话说,类A称为类B的一个子类)。
3)访问(access) 类B中的某些方法和变量,这取决于这些方法和变量的访问控制。
在效果上,访问意味着可见性(visibility)。如果类A不能“看到”类B内的方法和变量的访问级别无关紧要,类A将没有任何办法访问那些方法和变量。
默认访问。
package cert; class Beverage { }
现在请看第二个源文件:
package exam.stuff; import cert.Beverage; class Tea extends Beverage{ }
可以看出,超类(Beverage) 与子类(Tea)位于不同的包中。Tea文件顶部的import语句试图与导入Beverage类。Beverage文件可以很好地便于,但当试图编译Tea文件时,会得到类似如下的信息:
信息待定~
Tea将不会编译,因为超累Beverage具有默认访问,且位于不同包中。有两种办法解决这一问题:将两个类都放在同一个包中,或者像下一节所描述的那样讲Beverage声明为public。
当看到考题具有复杂逻辑时,一定要首先观察访问修饰符。这样,如果发现违规访问(例如,包A中的类试图访问包B中的默认类) ,就知道嗲吗不会编译,因此不必费时间来处理该逻辑。要知道,考试时间是最宝贵的。只需选择“Compilaction fails”答案,然后去回答侠义道题目即可。
公共访问
声明时带public关键 字的泪为来自所有包的所有类提供对公共类的访问。换句话说,Java University (JU)中的所有类都有全案访问public类。但是不要忘记,如果驶入使用的普遍立场类与你正在编写的泪位于不同包中,那么仍然需要导入这个public类。
在上一节的例子中,我们可能不希望将子类与超累放在同一个包中。为了使改代码生效,需要在超类(Beverage) 声明的前面加上关键字public,就像下面这样:
package cert; public class Beverage{}
这修改了Beverage类,因此,它对所有包中的所有类都将是可见的。现在,可以从所有其他类中实例化该类,而且任何一个类都可以任意地成为其子类(从它扩展)——除非该也标识了非访问修饰符final。细节请柬下面。
其他(非访问) 类修饰符
可以使用关键字final、abstract或strictfp修饰类声明,这些修饰符能够给加在所有类访问控制上。因此,举例来说,可以将类同时声明为public 和final。但是,不能总是混用非访问修饰符。例如可以随意组合strictfp和final,但是,永远不要将类同时标识为final和abstract。在接下来的两节中,将会一一讲述。
最终(final)类。当用于类声明时,final关键字指该类不能再有子类(即不能被子类化)。换句话说,任何其他类都不能扩展(继承自)final类,否则会编译错误而告终。
当需要确保类中的所有方法都不要被重写时,才应该建立final类。例如Java核心库中的许多类都是final类。
让我们修改Beverage例子,在声明中加入关键字final:
package cert; public final class Beverage{ public void importantMethod(){ } }
现在,如果尝试编译Tea子类:
package exam.stuff; import cert.Beverage; class Tea extends Beverage{ }
则会得到如下错误:
错误待定~
在实际使用中,几乎从不需要建立final类。final类湮没了面向对象的一个主要优点——可扩展性。
抽象(abstract) 类。abstract类永远不能被实例化。器唯一目的、人名和存在的理由是用于可扩展(即被子类化)。(但是要注意,可以编译并执行一个abstract类,只要不去试图创建它的实例即可。)为什么要建立一个不能从它产生对象的类呢?
因为类也可能是抽象的。例如,假设有一个Car类,它具有一些适用于所有车辆的通用方法,但是不能让任何人实际创建一个通用的、抽象的的Car对象。
它们该如何初始化器状态呢?它是什么颜色?有多少个座位?功率如何?等等……
这些问题都需要程序员实例化城市及的车辆类型,如BMWBoxster和SubaruOutback 。对于BMWBoxster的车主会告诉你:对于Subaru车主而言,BMWBoxster所能做的是,SubaruOutback“只有在梦中”才能做到。请看下面的abstract类:
abstract class Car{ private double price; private String model; private String year; public abstract void goFast(); public abstract void goUpHill(); public abstarct void impressNeighbors(); }
前面的代码能够编译。但是,如果试图在其他代码中实例化Car,就会得到如下编译错误:
错误待定~
注意,标志位abstract的方法一份好结尾,而不是一波形括号结尾的。