设计规约
将抽象数据类型的接口与其实现分离,并使用 Java 接口类型来强制这种分离。
定义带有接口的 ADT,并编写实现接口的类。
一、对象、类、属性、方法
类变量和类方法与一个类相关联,并且每个类出现一次。 使用它们不需要创建对象。
实例方法和变量在类的每个实例中出现一次。
实例⽅法也叫做对象⽅法。
类⽅法是属于整个类的,⽽实例⽅法是属于类的某个对象的。
由于类⽅法是属于整个类的,并不属于类的哪个对象,所以类⽅法的⽅法体中不能有与类的对象有关的内
容。即类⽅法体有如下限制:
(1) 类⽅法中不能引⽤对象变量;
(2) 类⽅法中不能调⽤类的对象⽅法;
(3) 在类⽅法中不能使⽤super、this关键字。
(4)类⽅法不能被覆盖。
如果违反这些限制,就会导致程序编译错误。
与类⽅法相⽐,对象⽅法⼏乎没有什么限制:
(1) 对象⽅法中可以引⽤对象变量,也可以引⽤类变量;
(2) 对象⽅法中可以调⽤类⽅法;
(3) 对象⽅法中可以使⽤super、this关键字。
在程序设计中,⼀些通⽤的、公⽤型的⽅法与类的对象⽆关,因此常常被作为类⽅法实现。如Java类库中
Math类,其中多数的数学运算操作都被定义成静态⽅法。因此,可以使⽤类⽅法把⼀些通⽤的、公⽤型的⽅
法放在合适的类中,从⽽很好地将它们组织起来。应⽤程序中的主⽅法main就是类⽅法。
1.在外部调⽤静态⽅法时,可以使⽤"类名.⽅法名"的⽅式,也可以使⽤"对象名.⽅法名"的⽅式。⽽实例⽅法只有后⾯这种⽅式。也就是说,调
⽤静态⽅法可以⽆需创建对象。
2.静态⽅法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态⽅法),⽽不允许访问实例成员变量和实例⽅法,如果需要调
⽤,则需要先实例化;实例⽅法则⽆此限制。
3.概念分析
静态⽅法是在类中使⽤staitc修饰的⽅法,在类定义的时候已经被装载和分配。⽽⾮静态⽅法是不加static关键字的⽅法,在类定义时没有占⽤内
存,⾮静态⽅法只有在类被实例化成对象时,对象调⽤该⽅法才被分配内存;
**注:**允许不创建对象⽽调⽤静态⽅法,是Java为了减少程序员调⽤某些常⽤⽅法时的麻烦,⽽允许程序员按照传统的C语⾔中使⽤函数的⽅式
来使⽤⽅法。典型的例⼦是前⾯某些程序中使⽤"Math.ramdon()"来获取随机数。
静态⽅法只能访问静态成员,实例⽅法可以访问静态和实例成员。之所以不允许静态⽅法访问实例成员变量,是因为实例成员变量是属于某个对象
的,⽽静态⽅法在执⾏时,并不⼀定存在对象。同样,因为实例⽅法可以访问实例成员变量,如果允许静态⽅法调⽤实例⽅法,将间接地允许它使
⽤实例成员变量,所以它也不能调⽤实例⽅法。基于同样的道理,静态⽅法中也不能使⽤关键字this。
main()⽅法是⼀个典型的静态⽅法,它同样遵循⼀般静态⽅法的规则,所以它可以由系统在创建对象之前就调⽤。
静态⽅法的优点:
静态⽅法可以⽅便在没有创建对象的情况下来进⾏调⽤(⽅法/变量)
二、接口和枚举
Java 的接口是一种用于设计和表达 ADT 的有用语言机制,它的实现是作为实现该接口的类
接口中不可以有构造方法;接口中的方法,实例化后一定都要实现;保证表示不变量;
因为 Java 中的接口不能包含构造函数,它们必须直接调用具体类的构造函数之一。
该构造函数的规范不会出现在接口中的任何地方,因此无法保证不同的实现甚至会提供相同的构造函数。
使用静态工厂代替构造方法。
三、继承和重写
3.1 Overriding
被final修饰的方法只可以被继承,而不可以重写它
个人理解,我们这个阶段可以认为overwrite和override是一个概念
当子类包含覆盖超类方法的方法时,它也可以使用关键字 super 调用超类方法
3.2抽象类
抽象方法由关键字abstract修饰,包含抽象方法的类就是抽象类,全是抽象方法的类就称为接口了。
如果某些操作是所有子类型都共有,但彼此有差别,可以在父类型中设计抽象方法,在各子类型中重写。
所有子类型完全相同的操作,放在父类型中实现,子类型中无需重写。有些子类型有而其他子类型无的操作,不要在父类型中定义和实现,而应在特定子类型中实现。
妈耶,这个修饰符到最后复习才搞清楚!!
四、多态、子类型、重载
4.1 多态的三种类型
Ad hoc polymorphism(特殊多态):当一个函数表示不同的和潜在的异构实现时,取决于有限范围的单独指定的类型和组合。 使用函数重载(功能重载)的许多语言都支持临时多态性。
§ 参数化多态(参数化多态):当编写代码时没有提及任何特定类型,因此可以透明地与任意数量的新类型一起使用。 在面向对象的编程社区中,这通常称为泛型或泛型编程。
§ 子类型化(也称为子类型多态性或包含多态性子类型多态、包含多态):当一个名称表示许多不同类的实例时,这些实例与某个共同的超类相关。
4.2特殊多态和重载
当一个函数作用于几种不同的类型(可能没有表现出共同的结构)并且对于每种类型可能以不相关的方式表现时,就会获得临时多态性。
重载必须是不同的参数列表哦!
可以在同一个类内重载,也可在子类中重载。
重载(对于类型)的解析是在编译阶段;
重写的解析(对于具体对象)的解析是在运行阶段;
对于重写:一定要把握住它是参数列表不可以变,返回值不可以变,里面的函数体核心可以改变
对于重载:一定要把握住,它的参数列表必须要改变,只有这一点限制,其他的想变就变,不想变不变
重载和重写的函数名都是相同的
对于后面两个格子的翻译:
引用类型确定选择哪个重载版本(基于声明的参数类型)。 在编译时发生。 实际调用的方法仍然是在运行时发生的虚方法调用,但编译器将始终知道要调用的方法的签名。 所以在运行时,参数匹配已经被确定,只是不是方法所在的实际类。
对象类型(换句话说,堆上实际实例的类型)决定了选择哪个方法。发生在运行时。
4.3 参数多态性和泛型编程
当一个函数在一系列类型上统一工作时,就会获得参数多态性; 这些类型通常表现出一些共同的结构。
– 它能够以通用方式定义函数和类型,以便它基于运行时传递的参数工作,即允许静态类型检查而不完全指定类型。
– 这就是Java中所谓的“泛型”。
泛型编程是一种编程风格,其中数据类型和函数是根据稍后指定的类型编写的,然后在需要时为作为参数提供的特定类型进行实例化。
泛型编程的核心思想是从具体、高效的算法中抽象出来,以获得可以与不同数据表示相结合的泛型算法,从而生成各种有用的软件
我们没有为 Set 、 Set 等编写单独的规范和实现,而是设计并实现了一个 Set 。
泛型接口+非泛型的实现类
泛型接口+泛型的实现类
4.4 子类型多态
继承/子类型的好处:代码重用、建模灵活性
Java中:每个类只能直接继承一个父类; 一个类可以实现多个接口
如果 S 是 T 的子类型,那么类型 T 的对象可以被类型 S 的对象替换(即类型 T 的对象可以被子类型 S 的任何对象替换),而不会改变 T 的任何所需属性。
五、一些重要的对象方法
例子
hashcode只要用到属性了,保证唯一就可以
修改方法: