多态表示同一个操作作用在不同对象时,会有不同的结果。

多态可分为编译时多态和运行时多态。

编译时多态:方法重载,编译时就可以确定到底调用哪个方法,可以被看做一个类中的方法多态性。

运行时多态:只有在运行时才能确定调用哪个方法,方法重写实现的多态是运行时多态。子类可以重写父类的方法,因此同样的方法在父类与子类有不同的表现形式。有两个必要条件:

-满足继承关系

-父类引用指向子类对象(向上转型、隐式转型、自动转型     小 -> 大)  Animal one=new Cat();   或者Animal one=new Cat();  Cat cat=new Cat();   one=cat;

多态的表现

Java中,父类的引用变量不仅可以指向自己的类型的实例对象,也可以指向其子类的实例对象。程序调用的方法在运行期才动态绑定,就是引用变量所指向的具体实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变量的类型中定义的方法。这种动态绑定的方法实现了多态。

父类类型创建子类对象,该对象可以调用父类派生的方法,子类重写的方法,但不能使用子类独有的方法。

public class Base {
public Base(){
g();
}
public void f(){
System.out.println("Base f()");
}
public void g(){
System.out.println("Base g()");
}
} public class Derived extends Base {
public void f(){ //重写了父类的f()
System.out.println("Derived f()");
}
public void g(){ //重写了父类的g()
System.out.println("Derived g()");
}
public void d(){ //子类独有的方法
System.out.println("d()");
}
} public class Test {
public static void main(String[] args){
Base b=new Derived(); //调用父类构造函数,由于多态性,会调用子类重写的g()方法
b.f(); //调用子类重写的f()方法
//b.d(); 编译报错,由于子类对象为父类引用指向,不能调用自己独有的方法
}
}

子类引用指向父类对象(向下转型、强制类型转换),与向上转型相比,它可以调用子类特有的方法,但必须满足转换条件。

Animal  one =new Cat();     //对象one是自动转为Animal类型,但是Cat类的实例

Cat temp=one;  //编译报错 ,需强制类型

Cat temp=(Cat)one;

Dog temp2=(Dog)one;   //编译报错,不满足转换条件,父类类型指向的实例化对象,只能强转换回对象对应的类型。

instanceof运算符

对象instanceof类,返回true/false,判断它左边的对象是否是它右边的类的实例,也就是判断对象是否满足某个特定类型实例特征,该运算符返回boolean类型的数据。

这样在进行向下强转类型时,就可以用instanceof来判断是否可以进行强转。

public class Test {
public static void main(String[] args){
Animal one =new Cat();
//Cat和Dog都继承Animal类
if(one instanceof Cat){ //常放在类型强转前
Cat temp=(Cat)one; //满足强转条件
System.out.println("one可以转换为Cat类型");
}
if(one instanceof Dog){
Dog temp=(Dog)one;
System.out.println("one可以转换为Dog类型");
}
if(one instanceof Animal){ //Animal是实例one的父类,所以one具有Animal特征
System.out.println("Animal");
}
if(one instanceof Object){ //Object是Animal的父类,所以one具有Object的特征
System.out.println("Object");
}
}
} //运行结果
one可以转换为Cat类型
Animal
Object

之前方法重写说,返回值类型要相同,返回值为父类类型的时候,在方法重写时是可以向下兼容的,但不能向上兼容,例如下例,方法重写返回为子类类型是可以的,但是Object不行。

父类

public Animal create(){ return new Animal();}

子类

@Override

public Dog create(){ return new Dog();}

static修饰的类方法,属于类共享,只能被继承,不能被重写。即使在子类出现同名的方法,也是子类独有的方法。

父类中的静态方法无法被子类重写,所以向上转型之后,只能调用到父类原有的静态方法。如果想调用子类自己的独有的静态方法,需要类型再转回来。

Animal one=new Cat();  one.say();  //调用父类静态方法

Cat two=(Cat)one;     two.say();   //调用自己的独有的静态方法

如果有一个饲养员类,去喂养不同的动物,每个动物的特征行为又不同。编写方法,传入不同类型的动物对象,调用各自的方法。

public void feed(Cat cat){

cat.eat();      //重写父类方法

cat.playBall();    //独有方法

}

public void feed(Dog dog){

dog.eat();      //重写父类方法

dog.sleep();    //独有方法

}

那如果有好多动物,要写一堆动物及他们各自的独有方法,有点儿麻烦。

也可以这样实现:

传入动物的父类,方法中通过类型转换,调用指定子类的方法。

public void feed(Animal obj){

if(obj instanceof Cat){

Cat temp=(Cat)obj;

    temp.eat();   //如果只有这个吃的方法就不需要类型判断,强制转换了,因为可以直接调用重写父类的方法

    temp.playBall();   //子类自己独有的方法,只能强制转换回自己的类型,否则作为父类类型不能直接调用子类独有的方法

  }else if(obj instanceof Dog){

    Dog temp=(Dog)obj;

    temp.eat();

    temp.sleep();

  }

}

第二种比第一种编码效率会高,但如果再新增其它类的话,要在这个方法里面进行修改,会破坏已有方法的封装性。

只有类中的方法才有多态的概念,类中成员变量没有多态的概念。成员变量是无法实现多态的,成员变量的值取决父类还是子类并不取决于创建对象的类型,而是取决于所定义变量的类型,这是在编译期间确定的。

class Base{

  public int i=1;

}

class Derived extends Base{

  public int i=2;

}

public class Test{

  public static void main(String[] args){

    Base b=new Derived();

    System.out.println(b.i);

  }

}

运行结果:1

Java基础笔记(十八)——多态的更多相关文章

  1. Java基础笔记-抽象,继承,多态

    抽象类: abstract修饰 抽象方法必须定义在抽象类中,抽象类不能创建对象. 在抽象方法中可以不定义抽象方法,作用是:让该类不能建立对象. 特点是: 1.定义在抽象类中 2.方法和类都用abstr ...

  2. java基础(十八)IO流(一)

    这里有我之前上课总结的一些知识点以及代码大部分是老师讲的笔记 个人认为是非常好的,,也是比较经典的内容,真诚的希望这些对于那些想学习的人有所帮助! 由于代码是分模块的上传非常的不便.也比较多,讲的也是 ...

  3. Java学习笔记十八:Java面向对象的三大特性之封装

    Java面向对象的三大特性之封装 一:面向对象的三大特性: 封装 继承 多态   二:封装的概念: 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访 ...

  4. java基础第十八篇之单元测试、注解和动态代理

    1:单元测试 1)JUnit是一个Java语言的单元测试框架,这里的单元指的就是方法 2)单元测试用来替换以前的main方法 1.1 Junit测试的步骤 1:在方法的上面加上 @Test 2:将ju ...

  5. Java基础(十八)集合(5)Queue集合

    队列是只能在尾部添加元素,同时只能在头部删除元素的数据结构.队列的原则就是“先进先出”. Queue接口是Collection接口的最后一个子接口. Queue接口是队列接口,而Deque接口是Que ...

  6. 夯实Java基础(十八)——泛型

    1.什么是泛型 泛型是Java1.5中出现的新特性,也是最重要的一个特性.泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类. ...

  7. 第二十九节:Java基础知识-类,多态,Object,数组和字符串

    前言 Java基础知识-类,多态,Object,数组和字符串,回顾,继承,类的多态性,多态,向上转型和向下转型,Object,数组,多维数组,字符串,字符串比较. 回顾 类的定义格式: [类的修饰符] ...

  8. Java IO(十八) BufferedReader 和 BufferedWriter

    Java IO(十八) BufferedReader 和 BufferedWriter 一.介绍 BufferedReader 和 BufferedWriter 是字符缓冲流,分别继承自 Reader ...

  9. Bootstrap <基础二十八>列表组

    列表组.列表组件用于以列表形式呈现复杂的和自定义的内容.创建一个基本的列表组的步骤如下: 向元素 <ul> 添加 class .list-group. 向 <li> 添加 cl ...

  10. Java基础笔记 – Annotation注解的介绍和使用 自定义注解

    Java基础笔记 – Annotation注解的介绍和使用 自定义注解 本文由arthinking发表于5年前 | Java基础 | 评论数 7 |  被围观 25,969 views+ 1.Anno ...

随机推荐

  1. xcode编译静态库选择cpu架构

    此前编译了一个静态库,默认支持了armv7,armv7s,arm64 编译的话肯定是上面三个静态库分别编译出来,然后在把这三个合并成一个单独的库. 如果单个库的大小是10M,那编译总的库大概就30M了 ...

  2. LaTeX 控制图片的位置

    加感叹号来忽略“美学”标准. \begin{figure}[!htb] \usepackage{float}\begin{figure}[H]插到你代码相应的位置. 1,插入并列的子图 \usepac ...

  3. eclipse 中使用 GreenUML 和 AmasterasUML 自动生成类图

    Green UML和AmaterasUML 两种 一.安装方法: 1.都是先安装GEF 通过eclipse-> install new software安装GEF的网址: http://down ...

  4. [poj3041]Asteroids(二分图的最小顶点覆盖)

    题目大意:$N*N$的网格中有$n$颗行星,若每次可以消去一整行或一整列,求最小的攻击次数使得消去所有行星. 解题关键:将光束当做顶点,行星当做连接光束的边建图,题目转化为求该图的最小顶点覆盖,图的最 ...

  5. 使用HttpClient进行Get通信

    --------------siwuxie095                             首先到 Apache官网 下载相关的库文件     Apache官网:http://www.a ...

  6. webform 内置对象(页面间传值)

    QueryString/URL传值  页面名后面加?变量名=值 有点:不占服务器内存. 缺点:保密性差:传递字符串长度有限. Response   --相应请求对象 Response.Redirect ...

  7. 算法Sedgewick第四版-第1章基础-015一stack只保留last指针

    /************************************************************************* * * A generic queue, impl ...

  8. CentOS6.5 安装python

    前言: CENTOS 6.X 系列默认安装的 Python 2.6 ,目前开发中主要是使用 Python 2.7 ,这两个版本之间还是有不少差异的,程序在 Python 2.6 下经常会出问题. 比如 ...

  9. 100723H Obfuscation

    传送门 题目大意 给你一个包含n 个单词的字典,给你一篇文章,文章包括若干词典里的单词,把句子里的空格都去掉,单词的首位字母都不变,中间的字符集为乱序,问能否恢复这篇文章,使得单词都是词典里的单词,如 ...

  10. 如何在Eclipse中如何自动添加注释和自定义注释风格

    1. 如何自动添加注释 可通过如下三种方法自动添加注释: (1)输入“/**”并回车. (2)用快捷键 Alt+Shift+J(先选中某个方法.类名或变量名). (3)在右键菜单中选择“Source ...