面向对象的编程
对象是类的一个实例,有状态和行为。
比如,一只狗是一个对象,他有几种状态(名字、颜色、饥饿,品种等等),以及几种行为(叫,摇尾巴等等);自行车有齿轮,速度,踏板节奏等状态,有改变齿轮,改变速度等行为。
类是一个模板,描述了一类对象的行为和状态。
每个对象都有一个类。类定义了属性类型以及行为实现。
接口:接口定义ADT,类实现接口。
接口之可以相互继承。
一个类可以实现多个接口,一个接口也可以有多个实现,
接口和类在使用时必须知道对应的实现该接口的名称,比如List<string> a=new ArrayList<>()
为了解决这个问题,可以在接口里加入静态工厂函数,在静态工厂函数中返回某一类型的值。
不同的实现是为了不同的表现、不同的行为以及经常的改变。
接口的好处:
Safe from bugs
ADT是由其操作定义的,接口就是这样做的。
当客户端使用接口类型时,静态检查确保他们只使用由接口定义的方法。
如果实现类公开其他方法,或者更糟糕的是,具有可见的表示,客户端不会意外地看到或依赖它们。
当我们有一个数据类型的多个实现时,接口提供方法签名的静态检查。
Easy to understand
客户和维护人员确切知道在哪里查找ADT的规约。
由于接口不包含实例字段或实例方法的实现,因此更容易将实现的细节保留在规范之外。
Ready for change
通过添加实现接口的类,我们可以轻松地添加新类型的实现。
如果我们避免使用静态工厂方法的构造函数,客户端将只能看到该接口。
这意味着我们可以切换客户端正在使用的实现类,而无需更改其代码。
继承与Override
Overriding
Rewritable methods:可以被重新实现(重写)的方法
Strict inheritance:严格继承,子类只能添加新的方法,不能重写超类中的方法。
Java中不能被重写的方法需要在生命中加入final关键字。
final:1)A final field:初始化后无法再次赋值
2)A final method:防止这个方法被Override
3)A final class:防止类的继承。
重写的函数需要有完全一样的函数声明(最好用@override标注),返回值可以更具体,访问控制可以更广,抛出更多的异常。
实际执行那个调用它的类中的版本,运行时决定。
super可以用来调用父类中函数的功能,并对其进行扩展,在构造函数里super只能放第一排。
方法重写的注意事项总结:
a)参数列表必须完全与被重写方法的相同;
b)返回类型必须完全与被重写方法的返回类型相同;
c)访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为public,那么在子类d)中重写该方法就不能声明为protected。
e)父类的成员方法只能被它的子类重写。
f)声明为final的方法不能被重写。
g)声明为static的方法不能被重写,但是能够被再次声明。
h)子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为private和final的方法。
i)子类和父类不在同一个包中,那么子类只能够重写父类的声明为public和protected的非final方法。
j)重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
k)构造方法不能被重写。
l)如果不能继承一个方法,则不能重写这个方法。
多态与overload
多态的三种类型:
特殊多态:功能重载
参数化多态:泛型
子类型多态:包含多态
特殊多态与重载:
重载:多个方法具有同样的名字,但有不同的参数列表或返回值类型
价值:方便client调用,client可用不同的参数列表,调用同样的函数
例如:
public class OverloadExample { public static String add(String c, String d) { return c.concat(d); } public static String add(String c, String d, String e){ return c.concat(d).concat(e); } public static int add(int a, int b) { return a+b; } }
重载的规则总结:
被重载的方法必须改变参数列表(参数个数或类型不一样);
被重载的方法可以改变返回类型;
被重载的方法可以改变访问修饰符;
被重载的方法可以声明新的或更广的检查异常;
方法能够在同一个类中或者在一个子类中被重载。
无法以返回值类型作为重载函数的区分标准。
重写与重载的区别
区别点 | 重载方法 | 重写方法 |
参数列表 | 必须修改 | 一定不能修改 |
返回类型 | 可以修改 | 一定不能修改 |
异常 | 可以修改 |
可以减少或删除,一定故不 能抛出新的或者更广的异常 |
访问 | 可以修改 | 一定不能做更严格的限制(可以降低限制) |
调用情况 |
引用类型决定选择哪个重载版本( 基于声明的参数类型)。 在编译时发生。 |
对象类型(换句话说,堆上实际实例的类型) 决定选择哪种方法在运行时发生。 |
泛型
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
可以写一个泛型方法,该方法在调用时可以接收不同类型的参数。根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用。
泛型类:其定义中包含了类型变量的类
泛型接口:定义中包含了类型变量的接口
泛型方法:定义中包含了类型变量的方法
泛型实例:
泛型接口实现的两种方式:
1)非泛型的实现类
对于实现Set<E>的接口
2)泛型接口:泛型的实现类
所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前(在下面例子中的<E>)。
每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像int,double,char的等)。
原文:https://www.cnblogs.com/boston-o/p/11074407.html