java中面向对象的三大特性:封装、继承、多态

封装

把抽象的数据和对数据的操作封装在一起,隐藏变量的实现细节。数据被保护在内部,程序的其他部分只有通过被授权的操作(成员方法)才能对数据进行访问。

1、原则

  • 将不需要对外提供的内容都隐藏起来
  • 把属性都隐藏,提供公共方法对其访问

2、好处

  • 将变化隔离
  • 便于使用
  • 提高重用性
  • 提高安全性
class FengZhuang{
private int age = 15;
public void setAge(int age) {
if (age > 0) {
this.age = age;
}
}
public int getAge() {
return this.age;
}
}

继承

java支持单继承,不直接支持多继承。

因为如果支持多继承,会产生调用的不确定性。(当继承的两个父类含有相同名字的方法时,不确定调用哪个。

继承可以解决代码复用的问题,当多个类存在相同的属性和方法时,我们可以从这些类中抽取出父类,在父类中定义这些属性和方法,只需要通过extends语句来声明继承父类。
父类的哪些属性可以被子类继承:

  • public
  • protected
  • 默认修饰符
  • private(只是继承后,相应的变量仍是私有的,不能直接访问)

1、子父类成员属性的特点package 继承;

public class Test1 {
public static void main(String[] args) {
Zi zi = new Zi();
zi.num = 3;//zi对象中没有自己写num属性,这个num属性是从父类中继承过来的
zi.show();
Zii zii = new Zii();
zii.show();  //奇怪,zi.num = 3 不是改变了父类中的num的值嘛?zii.show中的num不也应该等于3嘛?可是为什么等于2.可以知道成员继承只是实现了代码的复用,而不是内存的复用
} } class Fu{
int num1 = 1;
int num = 2;
} class Zi extends Fu{
int num2 = 4;
public void show() {
System.out.println(num + "..." + num);//3...3
System.out.println(this.num + "..." + super.num);//3...3 this 代表该类对象的引用。 super 代表一个父类空间。
System.out.println(num2 + "..." + num1);//4...1
}
} class Zii extends Fu{
public void show() {
System.out.println(this.num + "..." + super.num);//2...2
}
}

从上面的例子看成员变量的内存分析图。

2、子父类成员方法的特点

public class Test2 {
public static void main(String[] args) {
Demo1 d = new Demo1();
d.show();
}
} class Demo{
String name;
public void show() {
System.out.println("fu show run");
} public Demo() { } public Demo(String name) {//构造方法的重载
this.name = name;
}
} class Demo1 extends Demo{
public void show() {//父类方法的重写
System.out.println("zi show run");
}
}

函数的两个特性

1、重载(同一个类中)

  • 方法名可以相同
  • 方法的参数类型、个数、顺序至少有一项不同
  • 方法返回值类型可以不同
  • 方法的修饰符可以不同
  • 仅仅只是返回类型或修饰符不一样,不能构成重载

2、重写(子父类中)

  • 子类的方法的返回类型、参数、方法名、要和父类的完全一致(也就是说修饰符可以不一致,请看第二条),否则就不构成重写
  • 子类方法不能缩小父类方法的访问权限(即修饰符问题)
  • 什么时候使用重写:当对一个类进行子类的扩展时,子类需要保留父类的功能声明。但是要定义子类中该功能特有的内容时,可以使用重写。

3、子父类构造函数的特点

public class TestSuper2 {
public static void main(String[] args) {
System.out.println("开始创建一个ChildClass对象");
new ChildClass1(); }
} class FatherClass1 {
int m = 12;
static {
System.out.println("hello");
}
public FatherClass1() {
System.out.println(m);
System.out.println("创建FatherClass");
show();
}
public void show() { System.out.println("Father show");
}
}
class ChildClass1 extends FatherClass1 {
int num = 15; static {
System.out.println("hello1");
} public void show() {
System.out.println("Child show..." + num);
} public ChildClass1() {
super();
//super执行完后,才对子类ChildClass1进行成员变量的显示初始化
System.out.println(num);
System.out.println("创建ChildClass");
}
}

直接看运行结果,我们再来分析。在分析之前,我们先明确一个概念:构造函数用于对象的初始化,而静态初始化块用于类的初始化。

开始创建一个ChildClass对象
hello
hello1
12
创建FatherClass
Child show...0
15
创建ChildClass

分析:

  • 程序首先从main方法入手,先打印出“开始创建一个ChildClass对象”。之后创建一个ChildClass1的实例。
  • 在实例化之前,先进行类加载。先沿着继承树上溯到Object类。先执行Object类的静态初始化块,在向下执行子类的静态初始化块,直到我们实例化类的静态初始化块为止。类的初始化过程只进行一次。(即先进行类加载,类加载过程只进行一次)。这就是为什么会先后打印出hello和hello1。
  • 在堆内存中开辟空间,分配地址。并在对象空间中,对对象中的成员变量进行默认初始化。
  • 调用构造函数,进行特定数据的初始化(即this.name = name等)。这里要注意:在调用构造函数前已经完成成员变量的默认初始化。
  • 进入构造函数时,第一行会先调用父类的构造函数进行父类初始化。(调用父类的构造函数前,也已经完成了父类的默认初始化)。先后打印出:12,创建FatherClass,Child show...0。
  • 父类的super()函数执行完毕后,执行栈返回子类的构造函数,再对子类的成员变量进行显示的初始化。(此时输出15)
  • 最后进行的是对特定数据的初始化。即this.name = name等。

需要注意的是:成员变量的默认初始化是在调用构造函数之前,而显示初始化是在进入构造函数调用父类的super()方法之后。特定数据的初始化则在最后进行。

多态

1、成员属性的特点

package 多态;

public class chengyuanshuxing {
public static void main(String[] args) {
Fu zi = new Zi();
System.out.println(zi.num);//
}
} class Fu{
int num = 4;
} class Zi extends Fu{
int num = 5;
}

多态时,成员属性的特点:

  • 编译时,参考父类型上是否有调用的成员属性,有则编译通过,没有则编译失败。
  • 运行时,参考父类型中是否有该成员属性,运行该成员属性。
  • 简单说编译和运行都参考左边

2、成员函数的特点

package 多态;

public class chengyuanshuxing {
public static void main(String[] args) {
Fu zi = new Zi();
zi.show();//"zi show"
}
} class Fu{
void show() {
System.out.println("fu show");
}
} class Zi extends Fu{
void show() {
System.out.println("zi show");
}
}

多态时,成员函数的特点:

  • 编译时,参考父类型上是否有调用的成员方法,有则编译通过,没有则编译失败。
  • 运行时,参考的是对象所属的类中是否有该成员方法,运行该成员方法。
  • 简单说编译看左边,运行看右边

虽然类型是父类型,但是运行时this指向的是当前new实例的引用。

3、静态方法的特点

package 多态;

public class chengyuanshuxing {
public static void main(String[] args) {
Fu zi = new Zi();
zi.show();//"fu show"
}
} class Fu{
static void show() {
System.out.println("fu show");
}
} class Zi extends Fu{
static void show() {
System.out.println("zi show");
}
}

多态时,静态方法的特点:

  • 编译时,参考父类型上是否有调用的静态变量,有则编译通过,没有则编译失败。
  • 运行时,参考父类型中是否有该静态变量,运行该静态变量。
  • 简单说编译和运行都参考左边

静态方法是基于类的,而多态是基于对象的,所以调用时,该对象是那个类型的就调用相应类的静态方法。且静态方法不具有多态性

参考文章

Java类变量和成员变量初始化过程

Java中各成员变量初始化流程

java中面向对象的三大特性小结的更多相关文章

  1. Java基础-面向对象第三大特性之多态(polymorphism )

    Java基础-面向对象第三大特性之多态(polymorphism) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.多态概述 多态是继封装,继承之后,面向对象的第三大特性,多态的 ...

  2. JavaScript中面向对象的三大特性(一个菜鸟的不正经日常)

    经过几天的学习,把jQuery给啃会了,但是运用的还不算特别熟练,总感觉自己在JavaScript方面的基础十分欠缺,所以继续拾起JavaScript,开始更好的编程之旅~ 今天学的是JavaScri ...

  3. Java基础—面向对象的三大特性

    面向对象有三大特性分别是继承.封装和多态. (1)继承:继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法.对象的一个新类可以从现有的类中派生,这个过程称为类继承.新类 ...

  4. Go_15:GoLang中面向对象的三大特性

    有过 JAVA 语言学习经历的朋友都知道,面向对象主要包括了三个基本特征:封装.继承和多态.封装,就是指运行的数据和函数绑定在一起,JAVA 中主要是通过 super 指针来完成的:继承,就是指 cl ...

  5. GoLang中面向对象的三大特性

    有过 JAVA 语言学习经历的朋友都知道,面向对象主要包括了三个基本特征:封装.继承和多态.封装,就是指运行的数据和函数绑定在一起,JAVA 中主要是通过 super 指针来完成的:继承,就是指 cl ...

  6. Java中的第三大特性-多态性

    一.多态性的概念 多态性是以继承为基础上的,举个例子,人属于动物,狗也属于动物,所以动物就是父类,而人和狗都是动物的子类,都属于动物. 二.多态的使用 (1)多态一般用于方法参数或者方法返回值,特别当 ...

  7. 谈谈Java面向对象的三大特性

    Java面向对象的三大特性就是指封装.继承.多态了. 一.封装: 概念:封装是指隐藏对象的属性和实现细节,仅对外提供公共访问方式. (举例:笔记本电脑就是一个封装体,Java语言中最小的封装体就是函数 ...

  8. Java中面向对象三大特征

    也就是说在这里"人"是多态的, 在不同的形态时,特征行为是不一样的, 这里的"人", 同时有两种形态,一种是教师形态,一种是学生形态,所对应的特征行为分别是&q ...

  9. Java学习笔记二十五:Java面向对象的三大特性之多态

    Java面向对象的三大特性之多态 一:什么是多态: 多态是同一个行为具有多个不同表现形式或形态的能力. 多态就是同一个接口,使用不同的实例而执行不同操作. 多态性是对象多种表现形式的体现. 现实中,比 ...

随机推荐

  1. 「HNOI2010」合唱队

    题目链接 戳我 \(Solution\) 令: \(f[i][j]\)为\([i,j]\)中最后排进去的是第i人 \(dp[i][j]\)为\([i,j]\)中最后排进去的是第j人 则排头的元素即\( ...

  2. RDD与DataFrame

    RDD:分布式对象集合: 解决了:减少中间计算结果处理所需的开销   数据存在内存,提供一个通用的抽象的数据结构 惰性求值 DataFrame:分布式Row对象集合 服务于:SparkSQL

  3. 解决Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker fro问题

    项目中碰到一个问题,就是将一个map转换成json格式的时候出现错误,最后排查将延迟加载关闭后成功转换,因为数据量较大,于是重新创建了一个对象进行接收. 解决办法是在配置文件中进行配置 虽然解决了这个 ...

  4. Jmeter_远程启动

    Jmeter 是Java 应用,对于CPU和内存的消耗比较大,因此,当需要模拟数以千计的并发用户时,使用单台机器模拟所有的并发用户就有些力不从心,甚至会引起JAVA内存溢出错误. 其实,Jmeter的 ...

  5. ClickOnce发布包含某文件

    第一步.在文件上右键选择“属性”,“复制到输出目录”选择“始终复制”: 第二步.“生成操作”选择“选择”: 第三步.通过 项目右键属性-发布-应用程序文件 查看想要包含的文件是否包含进来了. 注:可以 ...

  6. c++多线程基础3(mutex)

    整理自:zh.cppreference.com/w/cpp/thread 互斥锁 互斥算法避免多个线程同时访问共享资源.这会避免数据竞争,并提供线程间的同步支持.定义于头文件 <mutex> ...

  7. python自带的排列组合函数

    需求: 在你的面前有一个n阶的台阶,你一步只能上1级或者2级,请计算出你可以采用多少种不同的方法爬完这个楼梯?输入一个正整数表示这个台阶的级数,输出一个正整数表示有多少种方法爬完这个楼梯. 分析:提炼 ...

  8. Linux原理与实践

    Linux 中的文件及权限 -rwxr-xr-x 1 cat animal 68 03-31 21:47 sleep.sh 三种用户角色: r 4 w 2 x 1 user ,文件的所有者 group ...

  9. Hibernate的工作流程以及三种状态

    Hibernate的工作流程: 1. 读取并解析配置文件 2.读取并解析映射信息,创建SessionFactory 3. 打开Sesssion 4.创建事务Transation 5. 持久化操作 6. ...

  10. 跟我一起读postgresql源码(二)——Parser(查询分析模块)

    上篇博客简要的介绍了下psql命令行客户端的前台代码.这一次,我们来看看后台的代码吧. 十分不好意思的是,上篇博客我们只说明了前台登陆的代码,没有介绍前台登陆过程中,后台是如何工作的.即:后台接到前台 ...