面向对象
抽象
概述
abstract 是一个修饰符:
修饰的类 是抽象类
修饰的成员方法 是抽象方法 , 并且该方法没有方法体({});
抽象的目的: 抽象类不能被实例化,只能用于被继承
一般抽象类中 , 有功能的定义 , 但是没有功能的实现 , 要求必须让子类复习
比如我们的Animal和Cat , 使用多态可以降低耦合度 , 但是Animal中其实只需要有移动方法即可,不需要实现
因为每个动物的移动方式不同 , 如果这个移动move方法, 不定义为抽象方法 , 那么子类就必须得复写这个
控制权力 得到反转
另外 , 因为抽象方法 , 是没有方法体(功能实现)的 , 那么肯定就不能被调用 , 但是如果有了对象 , 调用不调用就看调用处的
所以控制权就丢失了 ,所以 抽象类不能创建对象 , 自然抽象方法也就不能被调用了 , 这样既有获得了控制权 反转
含有抽象方法的类 , 必须是抽象类
但是 抽象类中不一定有抽象方法 , 比如我就想让某个类不能被实例化对象 ,也可以把该类定义为抽象类
final :
final 和 abstract不能同时出现
因为final 修饰的类不能被继承 , 而抽象类就是用来被继承的
因为final修饰的成员方法不能被覆写 , 而抽象方法就是用来被覆写实现的
如果一个非抽象类继承一个抽象类的话 , 必须实现抽象类中的所有方法
但是一个抽象类继承一个抽象类的话 , 可以实现0~N个抽象方法
abstract class Sup{
public Sup(){
//只是不能被创建对象,并不是没有构造方法
System.out.println("父类构造方法");
}
public void m1(){
System.out.println("父类m1");
}
public abstract void m2();
}
//普通类继承抽象类必须实现所有抽象方法
class Sub1 extends Sup{
@Override
public void m2(){
System.out.println("子类m2");
}
}
//抽象类继承抽象类,可以实现0~N个抽象方法
abstract class Sub2 extends Sup{}
接口
概述
引用类型 : 类 数组 接口
接口1.8之前只能有抽象方法和常量 , 完全抽象
但是1.8开始 , 也可以有静态方法和默认方法 , 还能有抽象方法
静态方法使用 接口名.方法名() 调用即可
default方法需要使用子实现类对象调用 , public default 返回值 方法名(参数){}
就可以把接口中的默认方法 , 当做类中的成员方法
接口中 public static abstract 都可以省略
1.9开始 支持private方法
接口可以看做是一个特殊的类 , 为了解决Java中单继承功能变弱问题 , 一个类智能有一个父类 , 但是可以有很多父接口
优点
面向接口编程
当一个柜功能拥有多种不同实现的时候 , 就需要依赖接口编程 , 此时可以降低耦合度
如果某一个功能 只拥有一种变化 , 则不需要面向接口编程
比如说 , 只有一种动物的时候 , 就是猫 , 那么就没有必要再创建一个Animal 然后再创建一个Cat去继承它了
但是有很多动物的时候 , 就需要这个Animal的存在了 , 可以降低耦合度 , 使用多态
比如下面的棋盘系统
如果B依赖的不是c , 而是c 的某一个实现的话 , 这样我们想要换游戏规则从 ,就不许要更改B的代码
但是如果B依赖的是c这个抽象的父类 ,那么想要换游戏规则 就只需要传入不容的c 的子类对象即可 ,因为多态(父类引用指向子类对象), 此时B的代码就无须该 , 这样就可以拥有更多的变化
使用
public interface Interface_01{
public static final String SUCCESS = "xxxx";
//psf可以省略 , 接口中没有变量只有常量 , 默认就是public
int AGE = 2;
//抽象方法 默认也是public的 abstract也可以省略
public abstract void m1();
public void m2();
void m3();
}
语法 :
[修饰符] interface 接口名{}
接口中的常量 public , static , final 可以省略
接口中的抽象方法 public abstract 可以省略
一个类可以实现多个接口
接口和接口之间是多继承
一个类实现一个接口需要实现所有的抽象方法
一个抽象类实现一个接口需要实现0~N个抽象方法
interface A1{
void m4();
}
interface A2{
void m5();
}
//就扣之间 多继承 多个用逗号隔开
interface A3 extends A1,A2{
void m6();
}
class B1 implements A1,A2{
@Override
public void m4();
@Override
public void m5();
}
//抽象类实现接口,可以实现0~N个抽象方法
abstract class B implements A{
@Override
public void m4(){
}
}
新特性
1.8开始 支持静态方法和默认方法
静态方法 : 接口名.方法名();
默认方法和抽象方法 : 子类方法.方法名();
接口没有构造方法 , 不能创建对象
interface C1{
//静态方法
public static void m1(){
System.out.println("静态m1方法");
}
//默认方法,就等于普通类中的成员方法
public default void m2(){
System.out.println("默认方法");
}
//抽象方法,就等于没有方法体的成员方法
public void m3();
}
public class Interface_02{
public static void main(String[] args){
C1.m1();
//C1 c = new C1();
C1 c = new D1();
c.m2();
c.m3();
}
}
class D1 implements C1{
@Override
public void m3(){
System.out.println("实现的m3");
}
}
类关系
1 继承 : 又叫泛化关系 , 使用关键字 extends表示
class 子类 extends 父类{}
类和类是单继承
interface 子接口 extends 父接口1,父接口2......{}
接口和接口之间是多继承
2 实现 implements
类和接口之间 是多实现关系
class 子类 implements 父接口1,父接口2....{}
3 依赖
某个类的方法中的局部变量,是另一个类对象的引用
这种关系是临时性的 , 方法执行完 关系就不存在了
4 关联
某个类的成员变量 , 是另一个类的对象引用
这个关系一半是长期的
5 聚合
整体和局部可以分离, 各自具有各自的生命周期
类似于公司和员工
把多个有独立功能的小模块 整合到一起 , 完成一个新的功能 ,就算功能完成 ,每个小模块还依然有它存在的价值
比如 A保存B 的引用 , 这个引用一般是调用处传递过来的 ,这样调用处和A都保存了B的引用
这个时候 就算A销毁了 B也不会销毁 因为还有其他引用指向
6 组合
组合的关系要强加于聚合 也有叫强聚合
同样是整体和局部 只不过不可分离 局部没有生命周期
比如人的身体 有腿 有眼睛 有大脑
比如 A保存B 的引用 这个引用一般是自己创建的(一般通过构造方法或者成员方法变量直接初始化)
这样每创建一个A 都会创建一个B A销毁B也会销毁
public class _01_test{
A b = new A();
public static void main(String[] args){
_01_Test t = new _01_Test();
t.m1();
System.out.println(t);
}
publci void m1(){
//依赖
B b1 = new B();
B b2 = new B();
B b3 = new B();
A a = new A();
B b4 = new B();
B b5 = new B();
B b6 = new B();
}
}
class A{}
Class B{
A a = new A();
A a1;
}
内部类
概述
当一个事物的内部 还有一部分需要一个完整的结构进行描述 而这个内部的完整发结构又只为外部事物提供服务 , 那么整个内部的完整结构最好使用内部类
在java中 允许一个类的定义位于另一个类的内部 前者称为内部类 后者称为外部类
Inner class 一般用定义在定义它的类或语句块之内 , 在外部引用它时必须给出完整的名称
内部类的最大优点 可以使用外部类的私有化数据
分类
静态变量 : 等同于静态内部类
类体中使用static修饰的类
成员变量 : 等同于普通的内部类
类体中没有static修饰的内部类
局部变量 : 局部内部类
方法中声明的内部类
形参/实参 : 匿名内部类
成员内部类
public class OuterClass{
private static String s1="A1";
private String s2="B";
//成员内部类
//可以使用权限控制修饰符:private protected public 默认
//成员内部类中不能有静态声明
//成员内部类中可以直接访问外部类中所有的数据
//先编译外部类, 在编译内部类
//类名为: 外部类$内部类 OuterClass$InnerClass
class InnerClass{
//public static void m1(){}
public void m2(){
System.out.println(s1);
System.out.println(s2);
}
}
}
public static void main(String[] args){
//外部类对象
OuterClass oc=new OuterClass();
//创建内部类对象 : 外部类对象.new 内部类();
InnerClass ic=oc.new InnerClass();
ic.m2();
}
3 依赖
某个类的方法中的局部变量,是另一个类对象的引用
这种关系是临时性的 , 方法执行完 关系就不存在了
4 关联
某个类的成员变量 , 是另一个类的对象引用
这个关系一半是长期的
5 聚合
整体和局部可以分离, 各自具有各自的生命周期
类似于公司和员工
把多个有独立功能的小模块 整合到一起 , 完成一个新的功能 ,就算功能完成 ,每个小模块还依然有它存在的价值
比如 A保存B 的引用 , 这个引用一般是调用处传递过来的 ,这样调用处和A都保存了B的引用
这个时候 就算A销毁了 B也不会销毁 因为还有其他引用指向
6 组合
组合的关系要强加于聚合 也有叫强聚合
同样是整体和局部 只不过不可分离 局部没有生命周期
比如人的身体 有腿 有眼睛 有大脑
比如 A保存B 的引用 这个引用一般是自己创建的(一般通过构造方法或者成员方法变量直接初始化)
这样每创建一个A 都会创建一个B A销毁B也会销毁