Java-基础-面向对象三大特性

Java-基础-面向对象三大特性

1. 封装

1、概念:

  将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。

2、好处:

  • 只能通过规定的方法访问数据。
  • 隐藏类的实例细节,方便修改和实现。 

3、封装的实现步骤

mark

需要注意:对封装的属性不一定要通过get/set方法,其他方法也可以对封装的属性进行操作。当然最好使用get/set方法,比较标准。

1.1 权限修饰符

修饰词 本类 同一个包的类 继承类 其他类
private × × ×
无(default) × ×
protected ×
public

1.2 this关键字

B、this关键字

 1.this关键字代表当前对象

  this.属性 操作当前对象的属性

  this.方法 调用当前对象的方法。

 2.封装对象的属性的时候,经常会使用this关键字。

 3.当getter和setter函数参数名和成员函数名重合的时候

1.3 内部类

内部类( Inner Class )就是定义在另外一个类里面的类。与之对应,包含内部类的类被称为外部类。

那么问题来了:那为什么要将一个类定义在另一个类里面呢?清清爽爽的独立的一个类多好啊!!

 答:内部类的主要作用如下:

 1. 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。

 2. 内部类的方法可以直接访问外部类的所有数据,包括私有的数据

  3. 内部类所实现的功能使用外部类同样可以实现,只是有时使用内部类更方便。

 内部类可分为以下几种:

  • 成员内部类

  • 静态内部类

  • 方法内部类

  • 匿名内部类  

2. 继承

  1. 继承的概念
  • 继承是类与类的一种关系,是一种“is a”的关系。比如“狗”继承“动物”,这里动物类是狗类的父类或者基类,狗类是动物类的子类或者派生类。如下图所示:

mark

  • 注:java中的继承是单继承,即一个类只有一个父类。
  1. 继承的好处
  • 子类拥有父类的所有属性和方法(除了private修饰的属性不能拥有)从而实现了实现代码的复用;

2.1 方法的重写

  • 子类如果对继承的父类的方法不满意(不适合),可以自己编写继承的方法,这种方式就称为方法的重写。当调用方法时会优先调用子类的方法。

重写要注意的是

  • 返回值类型
  • 方法名
  • 参数类型和个数

 都要与父类继承的方法相同,才叫方法的重写。

重载和重写的区别:

  • 方法重写:相对继承而言,子类中对父类已经存在的方法进行区别化的修改。
  • 方法重载:在同一个类中处理不同数据的多个相同方法名的多态手段

2.2 继承的初始化顺序

 基于上面两点,我们就知道实例化一个子类,java程序的执行顺序是:

 父类对象属性初始化—->父类对象构造方法—->子类对象属性初始化—>子类对象构造方法   

mark

2.3 final

 使用final关键字做标识有“最终的”含义。

  1. final 修饰类,则该类不允许被继承。

  2. final 修饰方法,则该方法不允许被覆盖(重写)

  3. final 修饰属性,则该类的该属性不会进行隐式的初始化,所以 该final 属性的初始化属性必须有值,或在构造方法中赋值(但只能选其一,且必须选其一,因为没有默认值!),且初始化之后就不能改了,只能赋值一次

  4. final 修饰变量,则该变量的值只能赋一次值,在声明变量的时候才能赋值,即变为常量

2.4 Super

 在对象的内部使用,可以代表父类对象。

  1、访问父类的属性:super.age

  2、访问父类的方法:super.eat()

 super的应用:

 首先我们知道子类的构造的过程当中必须调用父类的构造方法。其实这个过程已经隐式地使用了我们的super关键字。

 这是因为如果子类的构造方法中没有显示调用父类的构造方法,则系统默认调用父类无参的构造方法。

 那么如果自己用super关键字在子类里调用父类的构造方法,则必须在子类的构造方法中的第一行

3. 多态

面向对象的最后一个特性就是多态,那么什么是多态呢?多态就是对象的多种形态。

java里的多态主要表现在两个方面:

  1. 引用多态
  • 父类的引用可以指向本类的对象;
  • 父类的引用可以指向子类的对象;

这两句话是什么意思呢,让我们用代码来体验一下,首先我们创建一个父类Animal和一个子类Dog,在主函数里如下所示:

mark

注意:我们不能使用一个子类的引用来指向父类的对象,如:mark

  • 这里我们必须深刻理解引用多态的意义,才能更好记忆这种多态的特性。
  • 为什么子类的引用不能用来指向父类的对象呢?我在这里通俗给大家讲解一下:就以上面的例子来说,我们能说“狗是一种动物”,但是不能说“动物是一种狗”,狗和动物是父类和子类的继承关系,它们的从属是不能颠倒的。
  • 当父类的引用指向子类的对象时,该对象将只是看成一种特殊的父类(里面有重写的方法和属性),反之,一个子类的引用来指向父类的对象是不可行的!!
  1. 方法多态
  • 根据上述创建的两个对象:本类对象和子类对象,同样都是父类的引用,当我们指向不同的对象时,它们调用的方法也是多态的。
    • 创建本类对象时,调用的方法为本类方法
    • 创建子类对象时,调用的方法为子类重写的方法或者继承的方法;

使用多态的时候要注意:如果我们在子类中编写一个独有的方法(没有继承父类的方法),此时就不能通过父类的引用创建的子类对象来调用该方法!!!

注意: 继承是多态的基础。

3.1 引用类型转换

了解了多态的含义后,我们在日常使用多态的特性时经常需要进行引用类型转换。

3.1.1 向上类型转换(隐式/自动类型转换)

  • 是小类型转换到大类型。
  • 就以上述的父类Animal和一个子类Dog来说明,当父类的引用可以指向子类的对象时,就是向上类型转换。如:

mark

3.1.2 向下类型转换(强制类型转换)

  • 是大类型转换到小类型(有风险,可能出现数据溢出)。

  • 上述代码再加上一行,我们再次将父类转换为子类引用,那么会出现错误,编译器不允许我们直接这么做虽然我们知道这个父类引用指向的就是子类对象,但是编译器认为这种转换是存在风险的如:

mark
  • 那么我们该怎么解决这个问题呢,我们可以在animal前加上(Dog)来强制类型转换。如:

mark

  • 但是如果父类引用没有指向该子类的对象,则不能向下类型转换,虽然编译器不会报错,但是运行的时候程序会出错,如:

mark

  • 其实这就是上面所说的子类的引用指向父类的对象,而强制转换类型也不能转换!!
  • 还有一种情况是父类的引用指向其他子类的对象,则不能通过强制转为该子类的对象。如:

mark

这是因为我们在编译的时候进行了强制类型转换,编译时的类型是我们强制转换的类型,所以编译器不会报错,

而当我们运行的时候,程序给animal开辟的是Dog类型的内存空间,这与Cat类型内存空间不匹配,

所以无法正常转换。这两种情况出错的本质是一样的,所以我们在使用强制类型转换的时候要特别注意这两种错误!!下面有个更安全的方式来实现向下类型转换。。。。

3.1.3 instanceof

  • 来解决引用对象的类型,避免类型转换的安全性问题。
  • instanceof是Java的一个二元操作符。它的作用是测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据。

来使用instanceof运算符来规避上面的错误,代码修改如下:

mark

补充说明:

  • 在比较一个对象是否和另一个对象属于同一个类实例的时候,我们通常可以采用instanceof和getClass两种方法通过两者是否相等来判断,但是两者在判断上面是有差别的。
  • Instanceof进行类型检查规则是:你属于该类吗?或者你属于该类的派生类吗?而通过getClass获得类型信息采用==来进行检查是否相等的操作是严格的判断,不会存在继承方面的考虑
打赏
  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2019-2022 Zhuuu
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信