文章目录
一、抽象类和接口的特点
1.抽象类
注:
抽象类一定不能使用final修饰符,不可以同时使用,抽象类也不能用private修饰符一起使用(无法被实现)。
如果父类的业务方法没有办法实现,那就一定要设计成抽象的
比如计算图形的形状
2.接口
接口是一种特殊的类型,它有如下的特点:
接口可以多重继承的,一个接口可以继承多个接口;
一个类但可以实现多个接口;
接口本身是公开或者是默认的,默认的话,只能被同一个包中的类访问;
接口的所有属性都是公开静态常量默认p s f修饰 (编写代码时可以省略掉),它编译完也是.class文件;
接口的方法都是公开抽象方法(也可以省略),从jdk8开始接口中可以定义static方法和default方法;
注:
一个类实现了1个或多个接口,要实现这些接口中的所有的抽象方法,除非这个类是一个抽象类;
接口之间同样可以继承;
接口的类型,一般分成三种;
普通接口
常量接口,只有属性,没有方法的接口,在jdk5之后往往会被枚举代替。
标记接口,既没有属性,也没有方法的接口。如java.lang.Cloneable接口,标记接口可以针对一部分类做特殊处理
3.抽象类和接口的总结
1两者的异同
不同点:
1抽象类只能是单继承,接口可以多继承
2抽象类是部分抽象的,接口是完全抽象的在jdk8以前
相同点:
都是ADT(抽象数据类型),不能被实例化,它们都作为父类存在,或者说是编译时的类型,一起构成系统的“抽象类”
针对抽象类的应用场合:
类之间要满足IS A关系(实体-联系),一般不轻易使用,
多个子类要存在共性
针对接口的应用场合:
在任何时候,只要考虑到拓展性,伸缩性,都应该使用接口
接口就是规范,而且比骄灵活,尤其是jdk8之后,可以使用default关键字来给子类添加新功能
二、开发设计模式
简单工厂模式、模板模式、回调模式:
两种工厂模式:
1简单工厂:目的就是用来创建某一类对象/实例
实现的思路:
1.提供一个公开,静态方法,返回目标类型的实例
2.该方法可以重载
3.集中创建对象
2抽象工厂/复杂工厂:
模板模式:
它的使用场景:有固定的执行流程/步骤,其中有些步骤的实现需要子类来完成【父类完成不了】,这种情况下,我们就可以制定模板方法。
注:模板方法本身是不抽象的,而且应该使用final修饰符。
3回调模式【callback 设计模式有六大原则
合成复用原则,使用组合和聚合原则等等等等】:
往往都与模板配合使用。它是指当某个方法的实现需要依赖于调用者提供的局部实现时,此时,我们可以让调用者传入“这个局部的实现”,这个“局部的实现”就可以抽象为接口类型。
这里可以调用回调接口
如果方法的参数是接口的话,则在此方法一定会进行回调
比如:
// 回调接口,定义局部实现的方法
public interface Task {
void execute();
}
public class TaskExecutor {
// 模板方法,接受回调接口作为参数
public void run(Task task) {
System.out.println("准备执行任务...");
// 调用传入的回调接口实现
task.execute();
System.out.println("任务执行完毕。");
}
}
public class Main {
public static void main(String[] args) {
// 创建模板方法的执行器
TaskExecutor executor = new TaskExecutor();
// 通过匿名内部类传入回调实现
executor.run(new Task() {
@Override
public void execute() {
System.out.println("执行具体任务的逻辑!");
}
});
}
}
三、Object类和基本类型的包装类
Object类是Java所有类型直接或间接的超类。
它里面的公开以及protected 方法是所有JAVA对象都可以访问/使用的.常用的有:
toString 方法,它的本意是把对象以字符串的形式描出来并返回,主要是属性。可是,Object中是没有办法做到这一点的,因为它永远不知道有哪些类继承了它,所以,它采用的策略是提供一个默认的简单实现【返回此对象的16进制的内存地址】,并建议子类去重写这个方法
equals 方法,用来判断两个对象是否相等。此方法的默认实现就是比对象的内存地址。所以,我们的类也应该重写此方法,以从逻辑层面来定义对象是否相等)
hashcode 方法,默认是以内存地址来计算的。
clone 方法,克降对象,它的要求是:目标类型必需要实现java.lang.Cloneable 标记接口,否则抛异常。clone() 方法可能会导致浅拷贝(默认情况下只复制对象的引用,而不是嵌套对象的真实数据),这样可能产生意想不到的结果。如果类不打算被克隆,Java 会通过 CloneNotSupportedException 防止 clone() 的调用。
finalize 方法,本意是在GC收回对象之前,会回调对象的finalize方法,这样一来,我们程序员就可以利用这些次机会,在此方法中做一善后处理的工作。但是,由于GC的运行时机,程序员是不能控制的,所以,我们没有办法确定此方法的执行时间,所以,不建议使用。这里有两道线程,一个加载main方法,一个是垃圾回收,可以使用System.gc();
gelClass 方法,用来获取对象的运行时类型,返回类型是:Class
编写equals和hashcode方法的要求:
如果你使用 Eclipse IDE或者idea来生成的话,则无视这个要求,因为它是满足的。
如果你要手写这两个方法的实现,请遵守如下规则:
所有在equals方法考虑的属性,也必需出现在 hashcode方法中。
因为hashcode的算法要求:
如果对象的equals方法返回true,则他们的hashcode值必需一样。
如果对象的equals方法返回false,则尽最大努力保证它们的hashcode值不一样。
这里也是计算哈希值的方法里面乘一个质数31(应该是根据大量运算取的尽可能合理的数)的原因。
要实现对象的克隆,有如下要求:
1.重写Object类的 clone方法,把访问控制修饰符上升到 public
2.实现 java.lang.Cloneable 标记接囗
注:Object类中clone的默认实现只能做到浅拷贝。如果想实现深拷贝,只需要重新实现 clone 方法。
浅拷贝和深拷贝示例:
浅拷贝示例伪代码如下:
Student s1 = new Item (...); //创建实例1
Address base = new Base(...)
s1.setBaseAddress(base );
Student s2 = (Student)s1.clone(); //创建实例2,这里实例1和实例2中的base指向一个地址,所以只是实现了浅拷贝,它们共用一个base
深拷贝示例如下:
// Address类也需要实现Cloneable接口
class Address implements Cloneable {
private String province;
private String city;
private String street;
public Address(String province,