文档章节

java基础---->多态性

小强斋太
 小强斋太
发布于 2016/11/09 20:07
字数 1458
阅读 1
收藏 0
点赞 0
评论 0

多态性 

在面向对象中多态性实际上是面向对象里的一个最大的最有用的特点,对于多态性在java中有两种体现:

   1、  方法的重载及覆写

   2、  对象多态性:指的是父类对象和子类对象之间的转型操作

一、对象多态性:

继承允许将对象视为它本身或者它的父类的类型来处理,即将继承自同一父类的基类可以视为同一类处理,一份代码就可以毫无差别的运行在这些不同类型上。多态方法调用允许一种类型表现出与其他相似类型之间的区别,只要它们是从同一基类导出的。虽然这些方法都通过基类调用。

实现原理:后期绑定:在运行时根据对象的类型进行绑定。后期绑定也称为多态绑定或者运行时绑定。

Java中除了static方法和final方法(private方法属于final方法),其他的方法都是后期绑定。

只有普通方法调用时多态的。

对象多态性的例子

基类,形状类 Shape.java

public class Shape {
  public void draw() {}
  public void erase() {}
}

子类1,圆形 Circle.java

public class Circle extends Shape {
  public void draw() { System.out.println("Circle.draw()"); }
  public void erase() { System.out.println("Circle.erase()"); }
}

子类2,三角形 Triangle.java

public class Triangle extends Shape {
  public void draw() { System.out.println("Triangle.draw()"); }
  public void erase() { System.out.println("Triangle.erase()"); }
}

子类3,正方形 Square.java

public class Square extends Shape {
  public void draw() { System.out.println("Square.draw()"); }
  public void erase() { System.out.println("Square.erase()"); }
}

多态性体现

public class Shapes {

	public static void main(String[] args) {
		Shape shape1 = new Circle();
		Shape shape2 = new Triangle();
		Shape shape3 = new Square();

		shape1.draw();
		shape2.draw();
		shape3.draw();
	}
} 
/* Output:
Circle.draw()
Triangle.draw()
Square.draw()
*/

二、多态性理解:

 2.1只有非私有方法才可以被覆盖

“覆盖”私有方法:

class PrivateOverride {

    private void f() {

       System.out.println("privatef()");

    }

}

 

public class Derived extends PrivateOverride {

 

    public void f() {

       System.out.println("publicf()");

    }

 

    public static void main(String[] args) {

       PrivateOverride po = new Derived();

       po.f();//异常The method f() from the type PrivateOverride is not visible

    }

 

}


例子2:覆盖私有方法的现象,编译器不报错,但是不会按照我们期望的执行。

public class PrivateOverride {

    private void f() {

       System.out.println("private f()");

    }

 

    public static void main(String[] args) {

       PrivateOverride po = new Derived();

       po.f();

    }

}

 

class Derived extends PrivateOverride {

    public void f() {

       System.out.println("public f()");

    }

}

/*

 * Output: private f()

 */

2.2、父类和子类有相同的属性,且为public的情况疑问

只有普通方法的调用时多态的,如果访问某一个成员变量,该成员变量是public的,且父类子类都有这个属性,它的访问是在编译期进行解析。

虽然发生向上转型,Super sup = new Sub();sup.field就没有多态性,访问的是父类的field。

class Super {
	public int field = 0;

	public int getField() {
		return field;
	}
}

class Sub extends Super {
	public int field = 1;

	public int getField() {
		return field;
	}

	public int getSuperField() {
		return super.field;
	}
}

public class FieldAccess {
	public static void main(String[] args) {
		Super sup = new Sub(); // Upcast
		System.out.println("sup.field = " + sup.field + ", sup.getField() = "
				+ sup.getField());
		Sub sub = new Sub();
		System.out.println("sub.field = " + sub.field + ", sub.getField() = "
				+ sub.getField() + ", sub.getSuperField() = "
				+ sub.getSuperField());
	}
} 
/* Output:
sup.field = 0, sup.getField() = 1
sub.field = 1, sub.getField() = 1, sub.getSuperField() = 0
*/

2.3静态方法不具有多态性

如果某一个方法是静态的,它的行为就不具有多态性。

class StaticSuper {
	public static String staticGet() {
		return "Base staticGet()";
	}

	public String dynamicGet() {
		return "Base dynamicGet()";
	}
}

class StaticSub extends StaticSuper {
	public static String staticGet() {
		return "Derived staticGet()";
	}

	public String dynamicGet() {
		return "Derived dynamicGet()";
	}
}

public class StaticPolymorphism {
	public static void main(String[] args) {
		StaticSuper sup = new StaticSub(); // Upcast
		System.out.println(sup.staticGet());//静态方法,调用子类的
		System.out.println(sup.dynamicGet());//非静态方法
	}
}
/*
 * Output: Base staticGet() Derived dynamicGet()
 */

三、构造器内部调用的方法被子类覆盖的情况

构造器内部调用的方法被子类覆盖了。这个调用的效果很难预料,因为被覆盖的方法在对象被完全构造之前就会调用。这一定会造成一些难以发现的错误。

class Glyph {
	void draw() {
		System.out.println("Glyph.draw()");
	}

	Glyph() {
		System.out.println("Glyph() before draw()");
		draw();
		System.out.println("Glyph() after draw()");
	}
}

class RoundGlyph extends Glyph {
	private int radius = 1;

	RoundGlyph(int r) {
		radius = r;
		System.out.println("RoundGlyph.RoundGlyph(), radius = " + radius);
	}

	void draw() {
		System.out.println("RoundGlyph.draw(), radius = " + radius);
	}
}

public class PolyConstructors {
	public static void main(String[] args) {
		new RoundGlyph(5);
	}
} 
/* Output:
Glyph() before draw()
RoundGlyph.draw(), radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph(), radius = 5
*/

输出结果显示当Glyph的构造器调用draw()方法时候,radius不是默认初始值1而是0。

仔细分析这段代码,可以发现

1.在其他任何事物发生之前,将分配给对象的存储空间初始化成二进制的零。

2.如前所述那样调用基类构造器,此时,调用被覆盖后的draw()方法(注意,要在调用RoundGlyph构造器之前调用),由于步骤1的缘故,我们此时会发现radius的值为0

3.按照声明的顺序调用成员的初始化方法。

4调用导出类的构造器主体

这样有一个优点,至少保证所有的东西初始化为零或者null,而不仅仅是垃圾。其中通过‘组合’而嵌入到一个类内部的对象引用,其值是null,如果忘记为该值进行初始化,均会在运行时候出现异常。查看结果时候,发现其他所有的东西都是0.

结论:编写构造器的准则

用尽可能简单的方法使对象进入正常状态,可以的话,避免调用其他的方法。构造器内唯一能够安全调用的方法是基类中的final方法(也适用于private,它们自动属于final方法),这些方法不能被覆盖,因此也不会出现上述令人惊讶的问题。

四、向上转型

发生向上转型后,子类中自己的定义的操作是无法通过父类对象找到的。

class Useful {
	public void f() {}
	public void g() {}
}

class MoreUseful extends Useful {

	public void f() {}
	public void g() {}
	public void u() {}
	public void v() {}
	public void w() {}

}

public class RTTI {
	public static void main(String[] args) {
		Useful[] x = { new Useful(), new MoreUseful() };
		x[0].f();
		x[1].g();
//		x[1].u();// 编译错误 The method u() is undefined for the type Useful
		((MoreUseful) x[1]).u(); // 
		((MoreUseful) x[0]).u(); // 必须现有upCast才能有downCast,错误的向下转型,java.lang.ClassCastException
	}

}

© 著作权归作者所有

共有 人打赏支持
小强斋太
粉丝 0
博文 181
码字总数 0
作品 0
广州
有一到五年开发经验的JAVA程序员需要掌握的知识与技能!

JAVA是一种平台,也是一种程序设计语言,如何学好程序设计不仅仅适用于JAVA,对C++等其他程序设计语言也一样管用。有编程高手认为,JAVA也好C也好没什么分别,拿来就用。为什么他们能达到如此...

java高级架构牛人 ⋅ 06/02 ⋅ 0

「JAVA基础」面向对象的特征有哪些方面

老师为大家整理JAVA基础:面向对象的特征有哪些方面 面向对象的特征主要有以下几个方面: 1)抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关...

启示录是真的 ⋅ 06/01 ⋅ 0

作为一个java程序员这些技能你都知道吗?

一、Java特点 1、 面向对象 尽管受到其前辈的影响,但Java没被设计成兼容其他语言源代码的程序。这允许Java开发组自由地从零开始。这样做的一个结果是,Java语言可以更直接、更易用、更实际的...

java高级架构牛人 ⋅ 05/23 ⋅ 0

Java编程基础知识点和技术点归纳

Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于PC、数据中心、游戏控制台、科学超级计算机、移动电话和互...

Java小辰 ⋅ 05/23 ⋅ 0

Java开发学习之三版本简介 java编程

  Java编程语言,在更迭迅速的互联网领域多年屹立不倒,足以得见Java这门语言旺盛的生命力,因此,会有很多想要进入互联网领域的朋友,想要学Java来转行开发。但是,所谓“隔行如隔山”,j...

老男孩Linux培训 ⋅ 06/05 ⋅ 0

做几道基础的Java测试题,看看最近有进步吗?欢迎来学习

Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于PC、数据中心、游戏控制台、科学超级计算机、移动电话和互...

启示录是真的 ⋅ 05/24 ⋅ 0

学习大数据需要Java基础吗?

近几年,很多人都听到过一个名词“大数据”也有一部分人选择学习了解大数据,那么大数据到底是什么,学习大数据需要有Java基础吗? 推荐一个大数据学习交流群 119599574每天晚上20:10都有一节...

大数据大咖 ⋅ 06/10 ⋅ 0

leetcode算法题解(Java版)-1-二叉树遍历

又开始刷算法题了,正好在学Java,顺便也练练Java。 题目描述 Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right......

kissjz ⋅ 04/27 ⋅ 0

java编程学习常见面试题及答案

Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于PC、数据中心、游戏控制台、科学超级计算机、移动电话和互...

Java小辰 ⋅ 05/22 ⋅ 0

Java编程语言:Java的类型转换与多态

对于Java语言应该都不陌生,今天我们就将Java中的入门部分概念做一具体的讲解一下。 1.什么叫JVM,JRE,JDK? JRE 全称为JavaRunningEnvironment,就是我们所说的java运行环境,由java虚拟机和一...

启示录是真的 ⋅ 05/22 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

sbt网络问题解决方案

http://dblab.xmu.edu.cn/blog/maven-network-problem/

狐狸老侠 ⋅ 7分钟前 ⋅ 0

大数据,必须掌握的10项顶级安全技术

我们看到越来越多的数据泄漏事故、勒索软件和其他类型的网络攻击,这使得安全成为一个热门话题。 去年,企业IT面临的威胁仍然处于非常高的水平,每天都会看到媒体报道大量数据泄漏事故和攻击...

p柯西 ⋅ 50分钟前 ⋅ 0

Linux下安装配置Hadoop2.7.6

前提 安装jdk 下载 wget http://mirrors.hust.edu.cn/apache/hadoop/common/hadoop-2.7.6/hadoop-2.7.6.tar.gz 解压 配置 vim /etc/profile # 配置java环境变量 export JAVA_HOME=/opt/jdk1......

晨猫 ⋅ 56分钟前 ⋅ 0

crontab工具介绍

crontab crontab 是一个用于设置周期性被执行的任务工具。 周期性执行的任务列表称为Cron Table crontab(选项)(参数) -e:编辑该用户的计时器设置; -l:列出该用户的计时器设置; -r:删除该...

Linux学习笔记 ⋅ 今天 ⋅ 0

深入Java多线程——Java内存模型深入(2)

5. final域的内存语义 5.1 final域的重排序规则 1.对于final域,编译器和处理器要遵守两个重排序规则: (1)在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用...

江左煤郎 ⋅ 今天 ⋅ 0

面试-正向代理和反向代理

面试-正向代理和反向代理 Nginx 是一个高性能的反向代理服务器,但同时也支持正向代理方式的配置。

秋日芒草 ⋅ 今天 ⋅ 0

Spring 依赖注入(DI)

1、Setter方法注入: 通过设置方法注入依赖。这种方法既简单又常用。 类中定义set()方法: public class HelloWorldOutput{ HelloWorld helloWorld; public void setHelloWorld...

霍淇滨 ⋅ 昨天 ⋅ 0

马氏距离与欧氏距离

马氏距离 马氏距离也可以定义为两个服从同一分布并且其协方差矩阵为Σ的随机变量之间的差异程度。 如果协方差矩阵为单位矩阵,那么马氏距离就简化为欧氏距离,如果协方差矩阵为对角阵,则其也...

漫步当下 ⋅ 昨天 ⋅ 0

聊聊spring cloud的RequestRateLimiterGatewayFilter

序 本文主要研究一下spring cloud的RequestRateLimiterGatewayFilter GatewayAutoConfiguration @Configuration@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMi......

go4it ⋅ 昨天 ⋅ 0

Spring clound 组件

Spring Cloud技术应用从场景上可以分为两大类:润物无声类和独挑大梁类。 润物无声,融合在每个微服务中、依赖其它组件并为其提供服务。 Ribbon,客户端负载均衡,特性有区域亲和、重试机制。...

英雄有梦没死就别停 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部