Java中的多态

我们知道,面向对象有三大特征:封装、继承、多态
其中封装和继承比较好理解,我们重点来谈一谈多态,首先简单回顾一下封装和继承

1.封装

封装简单来说就是数据的隐藏;

封装的步骤:
1.使用private修饰需要封装的成员变量;
2.提供一个公开的方法设置或访问私有的属性;
例如: set属性名(…); //设置属性名
get属性名();//访问属性

封装的意义:

  • 隐藏代码的具体实现细节;
  • 统一用户的调用接口;
  • 提高系统的可维护性;

2.继承

  • 继承是类与类之间的一种关系,子类(派生类)继承父类(基类);
  • 类和类之间只能是单继承,接口可以多继承;
  • 父类中的属性和方法可以被继承,子类也可以重新定义或追加属性和方法等;若父类属性和方法用private修饰,在子类继承中就不可直接使用;
  • 父类中的构造器是不能被子类继承的,但子类的构造器会隐式调用父类无参构造器;

3.多态

什么是多态?父类引用指向子类对象,可以表现出不同的表现形式和形态;

多态的必要条件:

  • 继承:必须存在继承关系;
  • 重写:子类对父类中某些方法进行重写,在调用这些方法时就会调用子类的方法。
  • 向上转型:父类引用指向子类对象,这样该引用既能调用父类的方法,又能调用子类的方法;

多态情况下注意:

  • 一个对象的引用类型可以是该对象类型的任意父类型;
  • 父类和子类存在同名成员变量,无论静态或非静态,默认访问父类中的;
  • 父类和子类存在同名的非静态方法,默认访问的是子类的非静态方法;
  • 父类和子类存在同名的静态方法,默认访问的是父类的静态方法;
  • 不能访问子类特有的属性和方法

总结:只有同名非静态方法访问的才是子类的;

多态中方法的调用:

		public class Person{
            public void run(){
            }
        }
        public class Student extends Person{

        }
        //调用到的run方法,是Student从Person继承过来的run方法
        main:
            Person p = new Student();
            p.run();

 
        public class Person{
            public void run(){}
        }
        public class Student extends Person{
            public void run(){
                //重写run方法
            }
        }
        //调用到的run方法,是Student中重写的run方法
        main:
            Person p = new Student();
            p.run();

注意:子类继承父类,调用fun方法,如果fun方法在子类中没有重写,就调用子类继承父类的fun方法;
如果重写了,那么调用重写之后的方法;

来看下一个例子,如果是调用子类中独有的方法

 		public class Person{
            public void run(){
            }
        }
        public class Student extends Person{
            public void test(){
            }
        }
        main:
            Person p = new Student();    
		//编译报错,因为编译器检查变量p的类型是Person,但是在Person中没有发现test方法,所以编译报错.
            p.test();

原理:编译看左边,运行不一定看右边;
编译看左边的意思:java 编译器在编译的时候会检测引用类型中是否含有指定的成员,如果没有就会报错。test是子类特有的方法,所以他在父类中找不到就会报错;

如果要调子类test方法用则需要向下转型,需要把变量的类型进行转换;

           Person  p = new Student();
           Student s = (Student)p;
           s.test();
   或者
           //注意这种形式前面必须要两个小括号
           ((Student)p).go();  

引用数据类型之间的转换必须是父与子的关系,为了避免上述错误的发生,每次强转之前,应该使用instanceof进行判断,格式如下:
if(引用变量名x instanceof 目标类型y)
出结果是true还是false,主要是看变量x所指向的对象实际类型是不是Y类型的"子类型";
判断引用变量指向的对象是否为目标类型;

子类引用和父类引用指向对象的区别

//例如:Student类 继承 Person类
Student a = new Student();
Person b = new Student();

变量a只能调用Student独有的方法,包括继承来的方法;
变量b只能调用Person中有的方法,包括继承来的方法;

java中的方法调用,是运行时动态和对象绑定的,不到运行的时候,是不知道到底哪个方法被调用的;
重载是编译时多态;重写是运行时多态;

以下三种类型方法不能表现出多态(因为不能重写)

  1. static方法,因为被static修饰的方法属于类,而不属于实例(可以被子类继承,但不能重写);
  2. final修饰的方法
  3. private和protected修饰的方法
    private修饰的方法对子类不可见
    protected修饰的方法可以被子类重写,但无法被外部引用
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值