【Java基本功】一文了解Java中继承、封装、多态的细节

本节主要介绍Java面向对象三大特性:继承 封装 多态,以及其中的原理。

本文会结合虚拟机对引用和对象的不同处理来介绍三大特性的原理。

继承

Java中的继承只能单继承,但是可以通过内部类继承其他类来实现多继承。

public class Son extends Father{public void go () {System.out.println("son go");}public void eat () {System.out.println("son eat");}public void sleep() {System.out.println("zzzzzz");}public void cook() {//匿名内部类实现的多继承new Mother().cook();//内部类继承第二个父类来实现多继承Mom mom = new Mom();mom.cook();}private class Mom extends Mother {@Overridepublic void cook() {System.out.println("mom cook");}}}

封装

封装主要是因为Java有访问权限的控制。public > protected > package = default > private。封装可以保护类中的信息,只提供想要被外界访问的信息。

类的访问范围

 A、public    包内、包外,所有类中可见B、protected 包内所有类可见,包外有继承关系的子类可见(子类对象可调用)C、(default)表示默认,不仅本类访问,而且是同包可。D、private   仅在同一类中可见 

多态

多态一般可以分为两种,一个是重写,一个是重载。

  1. 重写是由于继承关系中的子类有一个和父类同名同参数的方法,会覆盖掉父类的方法。重载是因为一个同名方法可以传入多个参数组合。
  2. 注意,同名方法如果参数相同,即使返回值不同也是不能同时存在的,编译会出错。
  3. 从jvm实现的角度来看,重写又叫运行时多态,编译时看不出子类调用的是哪个方法,但是运行时操作数栈会先根据子类的引用去子类的类信息中查找方法,找不到的话再到父类的类信息中查找方法。
  4. 而重载则是编译时多态,因为编译期就可以确定传入的参数组合,决定调用的具体方法是哪一个了。

向上转型和向下转型:

  1. public static void main(String[] args) {
  2.    Son son = new Son();
  3.    //首先先明确一点,转型指的是左侧引用的改变。
  4.    //father引用类型是Father,指向Son实例,就是向上转型,既可以使用子类的方法,也可以使用父类的方法。
  5.    //向上转型,此时运行father的方法
  6.    Father father = son;
  7.    father.smoke();
  8.    //不能使用子类独有的方法。
  9.    // father.play();编译会报错
  10.    father.drive();
  11.    //Son类型的引用指向Father的实例,所以是向下转型,不能使用子类非重写的方法,可以使用父类的方法。
  12.    //向下转型,此时运行了son的方法
  13.    Son son1 = (Son) father;
  14.    //转型后就是一个正常的Son实例
  15.    son1.play();
  16.    son1.drive();
  17.    son1.smoke();
  18.    //因为向下转型之前必须先经历向上转型。
  19.    //在向下转型过程中,分为两种情况:
  20.    //情况一:如果父类引用的对象如果引用的是指向的子类对象,
  21.    //那么在向下转型的过程中是安全的。也就是编译是不会出错误的。
  22.    //因为运行期Son实例确实有这些方法
  23.    Father f1 = new Son();
  24.    Son s1 = (Son) f1;
  25.    s1.smoke();
  26.    s1.drive();
  27.    s1.play();
  28.    //情况二:如果父类引用的对象是父类本身,那么在向下转型的过程中是不安全的,编译不会出错,
  29.    //但是运行时会出现java.lang.ClassCastException错误。它可以使用instanceof来避免出错此类错误。
  30.    //因为运行期Father实例并没有这些方法。
  31.        Father f2 = new Father();
  32.        Son s2 = (Son) f2;
  33.        s2.drive();
  34.        s2.smoke();
  35.        s2.play();
  36.    //向下转型和向上转型的应用,有些人觉得这个操作没意义,何必先向上转型再向下转型呢,不是多此一举么。其实可以用于方法参数中的类型聚合,然后具体操作再进行分解。
  37.    //比如add方法用List引用类型作为参数传入,传入具体类时经历了向下转型
  38.    add(new LinkedList());
  39.    add(new ArrayList());
  40.    //总结
  41.    //向上转型和向下转型都是针对引用的转型,是编译期进行的转型,根据引用类型来判断使用哪个方法
  42.    //并且在传入方法时会自动进行转型(有需要的话)。运行期将引用指向实例,如果是不安全的转型则会报错。
  43.    //若安全则继续执行方法。
  44. }
  45. public static void add(List list) {
  46.    System.out.println(list);
  47.    //在操作具体集合时又经历了向上转型
  48. //        ArrayList arr = (ArrayList) list;
  49. //        LinkedList link = (LinkedList) list;
  50. }

总结: 向上转型和向下转型都是针对引用的转型,是编译期进行的转型,根据引用类型来判断使用哪个方法。并且在传入方法时会自动进行转型(有需要的话)。运行期将引用指向实例,如果是不安全的转型则会报错,若安全则继续执行方法。

编译期的静态分派

其实就是根据引用类型来调用对应方法。

  1. public static void main(String[] args) {
  2.    Father father  = new Son();
  3.    静态分派 a= new 静态分派();
  4.    //编译期确定引用类型为Father。
  5.    //所以调用的是第一个方法。
  6.    a.play(father);
  7.    //向下转型后,引用类型为Son,此时调用第二个方法。
  8.    //所以,编译期只确定了引用,运行期再进行实例化。
  9.    a.play((Son)father);
  10.    //当没有Son引用类型的方法时,会自动向上转型调用第一个方法。
  11.    a.smoke(father);
  12.    //
  13. }
  14. public void smoke(Father father) {
  15.    System.out.println("father smoke");
  16. }
  17. public void play (Father father) {
  18.    System.out.println("father");
  19.    //father.drive();
  20. }
  21. public void play (Son son) {
  22.    System.out.println("son");
  23.    //son.drive();
  24. }

方法重载优先级匹配

  1. public static void main(String[] args) {
  2.    方法重载优先级匹配 a = new 方法重载优先级匹配();
  3.    //普通的重载一般就是同名方法不同参数。
  4.    //这里我们来讨论当同名方法只有一个参数时的情况。
  5.    //此时会调用char参数的方法。
  6.    //当没有char参数的方法。会调用int类型的方法,如果没有int就调用long
  7.    //即存在一个调用顺序char -> int -> long ->double -> ..。
  8.    //当没有基本类型对应的方法时,先自动装箱,调用包装类方法。
  9.    //如果没有包装类方法,则调用包装类实现的接口的方法。
  10.    //最后再调用持有多个参数的char...方法。
  11.    a.eat(‘a‘);
  12.    a.eat(‘a‘,‘c‘,‘b‘);
  13. }
  14. public void eat(short i) {
  15.    System.out.println("short");
  16. }
  17. public void eat(int i) {
  18.    System.out.println("int");
  19. }
  20. public void eat(double i) {
  21.    System.out.println("double");
  22. }
  23. public void eat(long i) {
  24.    System.out.println("long");
  25. }
  26. public void eat(Character c) {
  27.    System.out.println("Character");
  28. }
  29. public void eat(Comparable c) {
  30.    System.out.println("Comparable");
  31. }
  32. public void eat(char ... c) {
  33.    System.out.println(Arrays.toString(c));
  34.    System.out.println("...");
  35. }
  36. //    public void eat(char i) {
  37. //        System.out.println("char");
  38. //    }

原文地址:https://www.cnblogs.com/xll1025/p/10257703.html

时间: 2024-10-10 15:33:07

【Java基本功】一文了解Java中继承、封装、多态的细节的相关文章

c语言中继承和多态的简单实现

C语言本身是不支持继承和多态的,但其实在 C 的世界里,有一套非常有名的面向对象的框架,用的也非常广,那就是 GObject,它是整个图形界面开发库 GTK 的基石,在IBM developerWorks上有一篇很好的文章介绍 GObject<GObject对象系统>.另外,在 Linux 内核里面也大量使用了面向对象的思想,比如虚拟文件系统,设备驱动等模块,在 lwn上有两篇文章就讲到了内核中的面向对象,详细请看:<Object oriented design patterns in

JavaScript基础--面向对象三大特性(八):继承封装多态

一.构造函数基本用法:function 类名(参数列表){属性=参数值} 1 function Person(name,age){ 2 this.name = name; 3 this.age = age; 4 } 5 6 //创建Person对象的时候,可以直接给名字和年龄 7 var p1 = new Person('abc',80); 8 window.alert(p1.name); 9 var p2 = new Person('hello',9); 10 window.alert(p2.

[转]Java中继承、多态、重载和重写介绍

什么是多态?它的实现机制是什么呢?重载和重写的区别在那里?这就是这一次我们要回顾的四个十分重要的概念:继承.多态.重载和重写. 继承(inheritance) 简单的说,继承就是在一个现有类型的基础上,通过增加新的方法或者重定义已有方法(下面会讲到,这种方式叫重写)的方式,产生一个新的类型.继承是面向对象的三个基本特征--封装.继承.多态的其中之一,我们在使用JAVA时编写的每一个类都是在继承,因为在JAVA语言中,java.lang.Object类是所有类最根本的基类(或者叫父类.超类),如果

C++中继承与多态

C++中的继承与多态是比较重要的一点,大致来讲解一下继承与多态的特点.继承是子类运用基类的成员以及成员函数,继承的方式分为public,protected以及private,今天主要讲解的是多态,多态是基类函数必有virtual.且是父类的指针指向子类的对象,例如: #include <iostream> #include <string> using namespace std; // class A { public: A() { cout << "A()

多继承,封装,多态,super()方法,类的约束

多继承: 多继承就是一个类里有多个父类,父类也可以有多个爷爷类.从多个父类中继承属性跟方法. 类的分类: python2.2之前,只有经典类,pythont2.2之后出现了新式类 经典类:不继承object类,多继承遵循深度优先,从左至右,一条路走到底 class A:pass 新式类:继承object类,多继承遵循c3算法,mro方法. class A(object):pass python3x版本只有新式类. 鸭子类型:两个结构类似,有弱关联关系的函数或者类. mro方法:(面试会考) 计算

面向对象的三大特征:继承 封装 多态

面向对象: 面向对象专注于由谁来解决这个过程,而调用者无需关注对象实现的细节 编程特点: 出现了一个个的类,从类中拿到对象,通过对象直接解决问题 类:具有一系列相同属性(特征)和方法(行为)的个体的集合 称为类 类是一个抽象的概念,只能说类具有哪些属性而不能直接对类进行赋值 例如 人类有身高这个属性,但是不能说人类的身高是180 对象:从类中拿出具有具体属性值的个体,称为对象 对象是从类中拿出的一个具体的个体,需要对属性进行具体的赋值 例如 人类有身高这个属性,张三是人类的一个个体,就可以说张三

java中继承和多态

转自原文http://blog.csdn.net/xinxin19881112/article/details/2944760 若冒犯博主,请勿见怪! 1.  什么是继承,继承的特点? 子类继承父类的特征和行为,使得子类具有父类的各种属性和方法.或子类从父类继承方法,使得子类具有父类相同的行为. 特点:在继承关系中,父类更通用.子类更具体.父类具有更一般的特征和行为,而子类除了具有父类的特征和行为,还具有一些自己特殊的特征和行为. 在继承关系中.父类和子类需要满足is-a的关系.子类是父类. 表

class中继承和多态简介

1.了解父类和子类的关系: 1 class Animal(object): 2 def run(self): 3 print("animal is running") 4 def run_twice(self): 5 self.run() 6 self.run() 1 class fish(Animal): 2 def run(self): 3 print("fish is not run, is fishing...") 1 class Tortoise(Anim

继承 封装 多态 简单介绍

面向对象的程序设计有三个主要特征,如: 封装性 ? 继承性 ? 多态性 封装: 不需要让外界知道的信息隐藏起来有些对象的属性及行为允许外界用户知道或使用,但不允许更改,而另一些属性或行为,则不允许外界知晓:或只允许使用对象的功能,而尽可能隐蔽对象的功能实现细节. 继承: 首先拥有反映事物一般特性的类,然后在其基础上派生出反映特殊事物的类 多态: 多态是允许程序中出现重名现象. Java 语言中含有方法重载与成员覆盖两种形式的多态. 方法重载:在一个类中,允许多个方法使用同一个名字,但方法的参数不