Java基础04 Java隐藏和封装类的继承多态

Posted discoverspace

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java基础04 Java隐藏和封装类的继承多态相关的知识,希望对你有一定的参考价值。

1 隐藏和封装

1.1 封装 Encapsulation

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

封装实现的目的如下:

(1)隐藏类的实现细节。

(2)让使用者只能通过实现预定的方法来访问数据,限制成员变量的不合理访问。

(3)能进行数据检查,有利于保证对象信息的完整性。

(4)便于修改,提高代码的可维护性。

良好的封装应该从两方面考虑:

(1)将对象的成员变量和实现细节隐藏起来,不允许外部直接访问。

(2)把方法暴露出来,让方法来控制对这些成员变量进行安全的访问和操作。

封装需要借助Java提供的访问控制符来实现。

技术图片

 一个类通常就是一个小的模块,我们应该让模块仅仅公开必须要让外界知道的内容,而隐藏其它一切内容。在进行程序设计时,要尽量避免一个模块直接修改或操作另一个模块的数据。模块设计追求强内聚(许多功能尽量在类的内部独立完成,不让外面干预)和弱耦合(提供给外部尽量少的方法调用)。

 

 2 类的继承

2.1 Java中的继承

单继承特点(每个子类只有一个直接父类)、用extends(拓展)关键字实现。实现继承的类称为子类(小),被继承的类称为父类(大)。例如水果和苹果的关系,苹果继承了水果,苹果是水果的子类,苹果是一种特殊的水果。父类包含的范围总比子类包含的范围大。

2.2 重写父类的方法

一般地,子类以父类为基础,额外再增加新的成员变量和方法。有一种情况是:当来自父类的某一种方法不能适应子类的需要时,子类需要重写(Override)继承自父类的方法。也成为方法覆盖(子类覆盖了父类的方法)。

方法的重写要遵循“两同两小一大”规则,“两同”即方法名相同、形参列表相同;“两小”指的是子类方法返回值类型应比父类方法返回值类型更小或相等,子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等;“一大”指的是子类方法的访问权限应比父类方法的访问权限更大或相等。尤其需要指出的是,覆盖方法和被覆盖方法要么都是类方法,要么都是实例方法,不能一个是类方法,一个是实例方法。

当子类覆盖了父类方法后,子类对象将无法访问父类中被覆盖的方法,但可以在子类方法中调用父类中被覆盖的方法(被覆盖的是实例方法用super,是类方法用父类类名)。

重写和重载:重载发生在同一个类的多个同名方法之间,重写发生在子类和父类的同名方法之间。

2.3 super限定

如果需要在子类方法中调用父类被覆盖的实例方法,则可以使用super限定来调用父类被覆盖的实例方法。

2.4 调用父类构造器

子类不会获得父类的构造器,但子类构造器里可以调用父类构造器的初始化代码,类似于一个构造器调用另一个重载的构造器。

用super。

技术图片

 super调用父类构造器,this调用重载构造器。

 创建任何对象总是从该类所在继承树最顶层类的构造器开始执行,依次向下执行,最后执行本类的构造器。如果某个父类通过this调用了同类中重载的构造器,就会依次执行父类的多个构造器。

 3 多态 Polymorphism

 3.1多态性

1.Java引用变量有两个类型: 一个是编译时类型,一个是运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,就可能出现所谓的多态。

 2.Java允许把一个子类对象直接赋给一个父类引用变量,无需任何类型转换,因此当把一个子类对象(如Son)直接赋给父类引用变量(如Father)时,语句Father son1=new Son(); ,son1的引用变量编译时类型是Father,运行时类型是Son,当运行时调用该引用变量的方法时,其方法行为总是表现出子类方法的行为特征,而不是父类方法的行为特征。这样就有可能出现相同类型的变量、调用同一个方法时呈现出多种不同的行为特征,这就是多态。

3.如果此时运行一段来自Son类中的Father所没有的方法,比如son1.test();,在Father中没有提供这个方法,因此会编译错误(编译时类型为Father)。(虚方法调用 仅有子类重写父类的方法

4.引用变量在编译阶段只能调用其编译时类型所具有的方法,但运行时则执行它运行时类型所具有的方法。因此,编写Java代码时,引用变量只能调用声明该变量时所用类里包含的方法。例如,通过Object p= new Person(代码定义一个变量p,则这个p只能调用Object类的方法,而不能调用Person类里定义的方法。

5.通过引用变量来访问其包含的实例变量时,系统总是试图访问它编译时类型所定义的成员变量,而不是它运行时类型所定义的成员变量。但可以通过引用变量的强转来改变。

3.2 引用变量的强制类型转换

编写Java程序时,引用变量只能调用它编译时类型的方法,而不能调用它运行时类型的方法,即使它实际所引用的对象确实包含该方法。如果需要让这个引用变量调用它运行时类型的方法,则必须把它强制类型转换成运行时类型,强制类型转换需要借助于类型转换运算符。
类型转换运算符是小括号,类型转换运算符的用法是: (ype)variable, 这种用法可以将variable 变量转换成-一个type类型的变量。前面在介绍基本类型的强制类型转换时,已经看到了使用这种类型转换运算符的用法,类型转换运算符可以将- -个 基本类型变量转换成另-个类型。
除此之外,这个类型转换运算符还可以将一-个引用类型变量转 换成其子类类型。这种强制类型转换不是万能的,当进行强制类型转换时需要注意:

1.基本类型之间的转换只能在数值类型之间进行,这里所说的数值类型包括整数型、字符型和浮点型。但数值类型和布尔类型之间不能进行类型转换。
2.引用类型之间的转换只能在具有继承关系的两个类型之间进行,如果是两个没有任何继承关系的类型,则无法进行类型转换,否则编译时就会出现错误。如果试图把一个父类实例转换成子类类型,则这个对象必须实际上是子类实例才行(即编译时类型为父类类型,而运行时类型是子类类型),否则将在运行时引发ClassCastException异常。

3.3 instanceof运算符

当把子类对象赋给父类引用变量时,被称为向上转型(upcasting),这种转型总是可以成功的,这也从另一个侧面证实了子类是一种特殊的父类。这种转型只是表明这个引用变量的编译时类型是父类,但实际执行它的方法时,依然表现出子类对象的行为方式。但把一个父类对象赋给子类引用变量时,就需要进行强制类型转换,而且还可能在运行时产生ClassCastException异常,使用instanceof 运算符可以让强制类型转换更安全。

instanceof运算符的前-个操作数通常是-一个引用类型变量,后一个操作数通常是-一个类(也可以是接口,可以把接口理解成一种特殊的类), 它用于判断前面的对象是否是后面的类,或者其子类、实现类的实例。如果是,则返回true,否则返回false。
在使用instanceof 运算符时需要注意: instanceof 运算符前面操作数的编译时类型要么与后面的类相同,要么与后面的类具有父子继承关系,否则会引起编译错误。

技术图片

 

 技术图片

 

以上是关于Java基础04 Java隐藏和封装类的继承多态的主要内容,如果未能解决你的问题,请参考以下文章

java 封装,继承,多态基础

JAVA基础整理-50.Java继承和多态

Java基础(多态的理解与应用)

Java10-java语法基础——java的封装性

Java基础知识

java面向对象的基本形式,封装继承多态