JAVA基础:抽象类,接口,instanceof,类关系,克隆
1 JDK中的包
-
JDK = JRE + 开发工具集(javac.exe)
-
JRE = JVM + java类库
-
JVM = java 虚拟机
-
jdk中自带了许多的包(类) , 常用的有
-
java.lang
该包中的类,不需要引用,可以直接使用。 例如:Object , System , String -
java.util
-
java.sql
-
java.net
-
java.io
-
java.text
-
2 抽象方法与抽象类
2.1 抽象方法
-
抽象方法,就是不具体的方法。
-
语法而言:哪里不具体? 没有方法体,具体的执行操作不知道
由abstract关键字修饰,没有方法体的方法,称为抽象方法
public void test1(){}
public abstract void test1();
-
逻辑而言:哪里不具体呢? 只清楚基本规则规范,但不确定具体的实现。
-
抽象方法怎么用?
-
抽象不能直接调用
-
抽象方法必须被子类重写,实际使用的是子类重写的方法。(抽象方法可以作为规则)
抽象方法不能被private修饰 ,不能被final修饰, 不能被static修饰
-
-
抽象方法必须写在抽象类或接口中
2.2 抽象类
-
由abstract关键字修饰的类,称为抽象类
public class A{}
public abstract class B{}
-
抽象类也是类,可以有构造方法,普通属性,普通方法 和 抽象方法
-
抽象类不能创建对象
-
抽象类的主要作用就是定义抽象方法。
-
抽象类必须被子类继承使用,并且子类要重写抽象类中的所有抽象方法,否则子类也是一个抽象类
-
抽象类中可以不包含抽象方法,但意义不大。
3 接口
-
接口是一个特殊的抽象类
-
接口中只能有抽象方法和静态的公共常量,没有普通方法 ,也没有构造方法,不能创建对象
-
接口使用interface关键字定义
class A{}
abstract class B{}
interface C{}
接口也必须被子类继承使用,子类继承接口称为 实现接口, 使用implements关键字完成类与接口的实现关系,子类被称为实现类
interface A{}
class B implements A{}
-
子类实现接口后,需要重写接口中的所有抽象方法,否则子类也是抽象类
-
子类可以实现多个接口
interface A{}
interface B{}
class C implements A , B{}
接口之间也可以继承,并支持多继承
interface A{}
interface B{}
interface C extends A , B{}
扩展
-
接口中的所有方法都是公共的抽象方法, 可以省略 public abstract
-
接口中的所有属性都是公共的静态常量属性,可以省略public static final
interface A{
void t1(); //public abstract void t1();
int i = 10 ; //public static final int i = 10 ;
}
扩展
-
jdk1.8之后,接口中可以提供非抽象方法
interface A{
default void t1(){}
}
随之而来的就是二义性问题
-
如果子类只实现了一个接口,其中的default方法可以不用重写 (因为是一个非抽象方法)
-
如果子类是实现了多个接口,其中有相同的default方法,要求必须重写default方法,表示哪一个父接口的方法都不继承。
逻辑上可以使用接口.super.method()语法,表示要继承哪一个父接口中的default方法
interface A{
default void t1(){
System.out.println("------------------");
}
}
interface B{
default void t1(){
System.out.println("==================");
}
}
class C implements A , B{
//理论上来说, C中拥有A的t1方法 和 B的t1方法 , 此时就存在二义性问题
//要求子类重写t1方法,表示谁也不继承
public void t1(){
B.super.t1(); //逻辑上表示继承B的t1方法
}
}
4 抽象类和接口选择问题
-
语法角度: 优先选择接口 (类单继承,接口多实现)
-
逻辑角度:
-
抽象类也是类,类是对象的模板,更倾向于对象不具体的设计场景
例如 : 门, 防盗门,卷帘门,电动门
-
接口中只有方法,没有属性,无法代表对象,代表的是行为能力
一般接口的命名多为 xxxxable , Runnable , Throwable , Clonable
-
5 类对象之间的关系
-
类是对象的模板, 对象可以简单的理解成生活中的人或物,人和人,人和物, 物和物存在着一定的关系
-
所以类,接口之间也存在的一定的关系
-
这些关系有强 ,有弱。 我们称之为耦合程度
我们希望编写耦合程度弱的程序。
-
类对象之间的关系有以下几种
5.1 继承关系
称为泛化关系 , 类和类继承, 接口和接口的继承都属于继承关系
class A{}
class B extends A{}
interface A{}
interface B extends A{}
继承是多态的基础 , 继承关系属于一种 is-a关系
继承关系是一种耦合度较强的关系
在UML建模时, 使用实线空心箭头
表示
5.2 实现关系
指的就是类实现接口 , 特点与继承关系相同,也属于泛化关系,也是一种is-a关系
interface A{}
class B implements A{}
在UML建模时, 使用虚线空心箭头
表示
5.3 包含关系
在一个类中,定义了另一个类型的属性 , 称之为 has-a关系
class A{}
class B{
A a ; //B中包含了一个A
A[] as ; //B中包含了一堆A
}
耦合程度要弱于继承关系
包含关系中随着包含程度的强弱,又分为3种包含情况
-
关联 : A 和 B两个类是同级别的, 没有所属关系 教师和学生
UML图中使用
实线箭头
-
聚合 : A 和 B两个类有组成关系,但又可以独立存在 车和轮
UML图中使用
空心菱形实线箭头
-
合成 : A 和 B两个类是组合关系,不能分开 人和四肢
UML图中使用
实心菱形实线箭头
- 无论是哪种关系,代码实现都是相同的,这三种关系属于逻辑上的分析与设计。
包含关系根据包含内容的数量分为3种包含情况
1.一对一
class A{}
class B{
A a ;
}
2. 一对多/多对一
class A{
B b;
}
class B{
A[] as ;
}
3.多对多
class A{
B[] bs ;
}
class B{
A[] as
}
5.4 依赖关系
在一个类的方法执行时,使用到另一个类对象 , 称之为use-a关系
相比于继承关系和包含关系, 依赖关系的耦合程度最弱
class A{}
class B{
public void t1(A a){
... use a ...
}
}
6 instanceof关键字
-
在多态应用种,判断某一个父类型变量中存储的对象是否属于某一种子类型
class A{}
class B extends A{} //B is-a A
class C extends B{} //C is-a B . C is-a A
A a = new B();
//c代表的是C对象
(a instanceof A) // true
(a instanceof B) // true
(a instanceof C) // false
(a instanceof Object) // true
(a instanceof String) // 报错
7 对象克隆
-
所谓的克隆,就是根据一个对象,创建另一个内容相同的新对象
-
需要对象备份的时候可以使用克隆
-
Object类中有一个clone方法,底层可以实现对当前对象的备份。
-
clone方法是一个protected方法,只能在子类中完成克隆,不能被外部对象强行克隆
-
需要子类重写clone方法,完成clone操作
-
同时还需要子类实现Cloneable接口
-
总结如何实现一个类对象的克隆?
-
子类实现Cloneable接口
-
子类重写clone方法
-
子类修改重写的clone方法的访问权限,改为public (是否支持外部克隆)
-
public class Goods implements Cloneable{
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
扩展 浅克隆与深克隆
存在一种包含关系
class A{}
class B{
A a ;
}
-
浅克隆 : 在克隆B的时候,,新的B对象中,a属性的地址与原来B对象中a属性的地址相同
-
深克隆:在克隆B的时候,新的B对象中,a属性 地址是一个新的A对象的地址
也就是说,不仅仅将B对象做了克隆,还将B对象包含的A对象也做了克隆
深克隆需要手动实现