Java 基础:面向对象的三大特征

目录:
一、 封装
二、 继承
三、 多态
四、 抽象类


一、封装

1. 概述
  • 定义:将类的某些信息隐藏在类的内部,不允许外部程序直接访问。只能通过该类提供的 特定的方法 来实现对隐藏信息的操作和访问,也就是:
    • 要隐藏对象的信息
    • 同时也要留出访问的接口
2. 封装的特点
  • 隐藏类的实现细节,实现了信息的隐藏及安全性,方便修改和实现
  • 提高了程序的模块化,提高系统独立性和软件的可重用性,且易于维护
  • 具体实现是编写该类的人控制的,让使用者只能通过事先定制好的 方法 来访问数据,实现者可以方便地加入控制逻辑,限制对属性的不合理操作
3. 封装的实现
  • 变量:使用 private 修饰,这就是变量的封装
  • 方法:也是一种封装,封装了多条代码
  • : 也是一种封装,封装了多个方法
  • 封装的实现步骤
    封装的实现
public class Cat {
    //成员属性:
    //修改属性可见性---private 限定只能在当前类内访问,只能修饰成员变量
    private String name;
    public Cat() {
    }
    //创建get/set方法
    //在get/set方法当中添加属性的限定
    public void setName(String name) {  //set方法一般没有返回值
        this.name = name;
    }
    public String getName() { 
        return "我是一只名叫"+this.name+"的猫咪";
    }
    public int getMonth() {
        return month;
    }
    public void setMonth(int month) {   //对年龄进行限定
        if(month<=0)
            System.out.println("输入信息错误,宠物猫的年龄必须大于0");
        else
            this.month = month;
    }
}

二、 继承

1. 概述
  • 一种类于类之间的关系,使用已存在的类作为基础建立新类。
  • 使用已存在的类的定义作为基础创建新类
  • 新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但 不能选择性地继承父类,必须继承父类 所有开放的特征
  • 使用 extends 关键字实现
2. 继承的逻辑关系
  • 不能为了继承某个功能而随意进行继承操作,必须要符合 “A is a B” 关系
3. 继承的特点:
  • 子类会自动拥有父类所有 非 private 修饰的属性和方法
  • 通过 子类对象 既可以调用自身的 非 private 修饰的成员,也可以调用父类的 非 private 修饰的成员
  • 父类 不可以 访问子类 特有成员,即使是共有的
  • 继承的出现提高了代码的复用性,提高软件开发效率。
  • 继承的出现让类与类之间产生了关系,提供了多态的前提
4. 继承的注意事项:
  • 在Java中,只支持单继承,不允许多继承,一个类只能有一个直接父类
  • 多个类可以继承一个父类:
class B extends A{}
class C extends A{}   // 类B和类C都可以继承类A
  • 在Java中,多层继承 是可以的,即一个类的父类可以再去继承另外的父类
class A{}
class B extends A{}   // 类B继承类A,类B是类A的子类
class C extends B{}   // 类C继承类B,类C是类B的子类,同时也是类A的子类
  • 在Java中,子类和父类是一种相对概念,一个类是某个类父类的同时,也可以是另一个类的子类。
5. 继承后子类父类成员变量的特点
  • 子类的对象调用成员变量的时候,子类自己有,使用子类,子类自己没有则调用父类
  • 子父类中出现了 同名 的成员变量时,在子类中需要访问父类中非私有成员变量时,需要使用 super 关键字
6. 继承后子类父类成员方法的特性
  • 子类的对象调用方法的时候,子类自己有,使用子类,子类自己没有调用的父类
  • 子类中出现与父类一模一样的方法时,会出现覆盖操作,也称为 override 重写、复写或者覆盖
7. 继承的初始化顺序
  • 父类中有:静态代码块,构造代码块,无参构造方法,静态属性。
  • 子类中有:静态属性,静态代码块,构造代码块,无参构造方法
  • 执行顺序
  1. 父类的静态代码块
  2. 子类的静态代码块
  3. 父类的构造代码块
  4. 父类的无参构造方法
  5. 子类的构造代码块
  6. 子类的无参构造方法
8. 方法重载和方法覆盖
  • 方法重载
  • 同一个类中
  • 方法名:重载的两个方法的方法名必须相同
  • 参数列表不同,三者至少满足一个(参数顺序、个数、类型),三者至少满足一个
  • 重载与返回值类型、权限修饰符 无关
  • 与方法的参数名 无关
  • 方法覆盖
  • 有继承关系的 子类 中, **子类覆盖父类的方法 **
  • 方法名:子类方法和父类方法 必须相同
  • 参数列表:子类方法和父类方法的形参列表 必须相同
  • 访问修饰符子类方法的权限 >= 父类的方法的权限
  • 返回值类型
    • 基本类数据类型: 必须相同
    • 引用数据类型相同 或者 子类方法的返回值类型是父类方法的返回值类型的 子类
  • 注意
    • 当子类重写父类方法后,子类对象调用的是 覆盖后 的方法。
    • 属性名也是一样的道理,没有重名之前,调用的是父类的,重名之后用的是子类的
    • final 修饰的方法不允许在子类中覆盖
    • 父类被覆盖的方法的参数列表中被声明为 final 的参数,在子类的覆盖方法的中可以不必指定为 final
    • 子类覆盖方法声明的 异常列表中的异常类 必须与父类被覆盖方法声明的异常列表中的异常类 兼容
    • 只有在 子类类体中可以访问 的父类或祖先类的方法才能被覆盖
    • 静态方法 不能被覆盖,只能被隐藏
    • 如果通过子类对象访问父类方法,在 父类类体 中,访问到的任然是子类中的覆盖方法

三、 多态

1. 概述
  • 定义:多种形态,是面向对象语言最核心特征,封装和继承都是为多态准备的,非常重要
  • Java中多态的 代码体现 在一个子类对象(实现类对象)既可以给这个子类(实现类对象)引用变量赋值,又可以给这个子类(实现类对象)的父类(接口)变量赋值。
  • 最终多态体现为 父类引用变量可以指向子类对象

如 Student 类可以为 Person 类的子类。那么一个S tudent 对象既可以赋值给一个 Student 类型的引用,也可以赋值给一个 Person 类型的引用。

  • 多态的分类:

    • Java中的多态一般是运行时多态
    • 编译时多态:设计时多态,方法重载来实现
    • 运行时多态:程序运行时动态决定调用哪个方法
  • 多态的前提:必须有 子父类关系 或者类 实现接口关系,否则无法完成多态。

  • 多态的优点

    • 提高代码的可维护行
    • 提高代码的扩展性
  • 多态的弊端:不能使用子类的特有功能

如何解决?
法1:创建子类对象调用子类方法
法2:把父类的引用强转为子类引用

2. 多态调用的三种格式
  • 父类的引用变量指向子类对象:父类类型 变量名 = new 子类类型();
  • 普通类多态定义的格式:父类 变量名 = new 子类();
  • 抽象类多态定义格式:抽象类 变量名 = new 抽象类子类();
  • 接口多态定义的格式:接口 变量名 = new 接口实现类();
3. 注意事项:
  • 同一个父类的方法会被不同的子类重写。在调用方法时,调用的为各个 子类覆盖后的方法
Person p1 = new Student();
Person p2 = new Teacher();
p1.work(); //p1会调用Student类中重写的work方法
p2.work(); //p2会调用Teacher类中重写的work方法
  • 当变量名指向不同的子类对象时,由于每个子类覆盖父类方法的内容不同,所以会调用不同的方法。
4. 多态中成员访问的特点
  • 成员变量
    • 编译看左边(引用变量的声明类型),运行看左边(实际访问到的成员变量的值,也是由引用变量的声明类型来决定)
  • 方法
    • 编译看左边(引用变量的声明类型),运行看右边(实际访问到的方法,是由引用变量所指向的对象的实际类型来决定)
5. 编译时多态(方法重载 overload)
  • 因为对于方法重载而言,虽然多个方法的方法名相同,但是我们的编译器,可以根据方法调用代码推断出,所要调用的那个方法的方法签名,从而根据方法签名(jvm唯一的),确定要调用的方法

** 注:方法签名: 方法名+方法参数列表**

6. 运行时多态
  • 因为在编译器编译的时候,无法知道,具体调用的是哪个方法的代码,只有当 jvm 具体真正执行到调用代码的地方,jvm才能知道调用的究竟是哪个方法
  • 实现运行时多态:继承、方法覆盖/重写(override)、父类引用指向子类对象
7. 多态的转型
  • 向上转型:当有 子类对象赋值给一个父类引用 时,便是向上转型,多态本身就是向上转型的过程。(也叫:隐式转型、自动转型)

    • 格式:父类类型 变量名 = new 子类类型();
  • 向下转型:一个 已经向上转型 的子类对象可以使用 强制类型转换 的格式,将父类引用转为子类引用,这个过程是向下转型。如果是直接创建父类对象,是无法向下转型的!

    • 格式:子类类型 变量名 = (子类类型) 父类类型的变量;
  • 什么时候使用向上转型?

当不需要面对子类类型时,通过提高扩展性,或者使用父类的功能就能完成相应的操作,这时就可以使用向上转型。

  • 什么时候使用向下转型?

当要使用子类特有功能时,就需要使用向下转型。
向下转型的好处:可以使用子类特有功能。
但是弊端是需要面对具体的子类对象;在向下转型时容易发生 ClassCastException 类型转换异常。在转换之前必须做 类型判断
如: if( !a instanceof Dog){…}

8. instanceof 关键字
  • 作用: 可以通过 instanceof 关键字来判断是否能够对象转化。也就是,一个引用型的变量,是不是这个类型的对象,提高向下转型的安全性

  • 格式boolean b = 对象 instanceof 数据类型; ,返回 true / false

注意null instanceof <类名> 结果永远是 false

Person p1 = new Student(); // 前提条件,学生类已经继承了人类
boolean flag = p1 instanceof Student; //flag结果为true
boolean flag2 = p2 instanceof Teacher; //flag结果为false

四、 抽象类

1. 概述
  • 在Java中,一个没有方法体的方法应该定义为抽象方法,而如果一个类中含有抽象方法,则该类必须定义为一个抽象类
  • 抽象类通常作为一个 框架(虽然在父类抽象类中,有些行为并不能具体确定,但是从类设计的角度将,我们能确定该类存在这样的行为),把子类将实现的抽象方法组织起来,简化或限制子类的设计
2. 抽象类的定义格式
  • 抽象方法定义的格式:
    public abstract 返回值类型 方法名(参数);

  • 抽象类定义的格式:
    abstract class 类名 {}

3. 抽象类特点
  • 抽象类和抽象方法都需要被 abstract 修饰。抽象方法一定要定义在抽象类中。
  • static、final、private 不能与 abstract 同时出现。
  • 抽象方法 不能有 方法体
  • 抽象类 不一定 有抽象方法,但是含有抽象方法的类 必须是 抽象类
  • 构造方法,类方法(用 static 修饰的方法),不能声明为抽象方法。
  • 抽象类本身不能实例化(但是多态机制可以用子类实例化),不可以直接创建对象

原因:调用抽象方法没有意义

  • 只有覆盖了抽象类中 所有的 抽象方法后,其子类才可以创建对象。否则该子类还是一个抽象类。
  • 抽象类只定义了类的部分行为(包含具体行为), 这些行为是 子类共有的,其它行为由子类实现的抽象方法提供
4. 抽象类成员特点
  • 抽象类的 成员变量:既可以变量,又可以是常量
  • 抽象类的 构造方法:用于父类数据的初始化

子类继承抽象类时,构造方法不会被覆盖。 而且,在实例化子类对象时首先调用的是抽象类中的构造方法再调用子类中的。
因此,在抽象类中可以使用构造方法封装,所继承子类公共的东西。

  • 抽象类的 方法:可以是抽象的,也可以是非抽象的,
    • 作用
      • 抽象的:强制子类实现 (语法上的强制约束力)
      • 非抽象的:子类可以复用
5.抽象类的子类(二选一)
  • 如果不想重写抽象类里面的抽象方法,则子类也必须是抽象类
  • 如果不是抽象类,则必须实现抽象父类的所有抽象方法
6. 抽象类的细节
  • 抽象类一定是个父类?

严格来说是的,不是父类的话就没有意义了,抽象类的抽象方法必须由子类来实现 本身只起到定义的作用

  • 抽象类中是否可以没有抽象方法?如果可以,那么,该类还定义成抽象类有意义吗?为什么?

可以没有抽象方法,有意义,是为了不让该类创建对象,方法可以直接让子类去使用
在实际开发中,有的时候,不希望使用者,直接实例化出一个类的对象,可以将这个类定义为 abstract

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容

  • 1 面向对象No6 面向对象 OO Object Oriented 编程时以对象为单元,封装数据和逻辑,以此提...
    征程_Journey阅读 1,054评论 0 2
  • 面向对象笔记 一、 对象在内存中的存放方法以及被调用过程 class文件首先被加载到方法区中的class文件内容区...
    VictorBXv阅读 427评论 0 2
  • 一、Java 简介 Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计...
    子非鱼_t_阅读 4,072评论 1 44
  • java继承 继承的概念 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。 继承就是子类继...
    863cda997e42阅读 629评论 0 1
  • 意兴阑珊,加之身体不适,若有什么能让纠结的内心暂时平缓一下的话,估计非书莫属。如想自由自在的看书,最好不过的是...
    朵墨阅读 614评论 0 2