ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

面向对象(封装 继承 多态 抽象类 接口 内存分析)

2020-12-12 18:32:40  阅读:140  来源: 互联网

标签:调用 静态方法 对象 子类 多态 面向对象 抽象类 父类 方法


面向对象

OOP详解

1.什么是面向对象

Java的编程语言是面向对象的,采用这种语言进行编程称为面向对象编程(Object-Oriented Programming, OOP)。
面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据。

从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象。
从代码运行角度考虑是先有类后有对象。类是对象的模板。

2.类与对象的关系

是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物。对象是抽象概念的具体实例。

3.对象和引用的关系

引用 “指向” 对象
使用类类型、数组类型、接口类型声明出的变量,都可以指向对象,这种变量就是引用类型变量,简称引用。
在程序中,创建出对象后,直接使用并不方便,所以一般会用一个引用类型的变量去接收这个对象,这个就是所说的引用指向对象。

方法回顾

1.方法的定义

语法:

修饰符 返回类型 方法名(参数列表)异常抛出类型{...}

注意

方法一定是定义在类中的,属于类的成员。

修饰符

public、static、abstract、final等等都是修饰符,一个方法可以有多个修饰符。如果一个方法或者属性有多个修饰符,这多个修饰符是没有先后顺序的

返回类型

方法执行完如果有要返回的数据,那么就要声明返回数据的类型,如果没有返回的数据,那么返回类型就必须写void。
只有构造方法(构造器)不写任何返回类型也不写void。

break和return的区别:

return 语句的作用:

  • return 从当前的方法中退出,返回到该调用的方法的语句处,继续执行。
  • return 返回一个值给调用该方法的语句,返回值的数据类型必须与方法的声明中的返回值的类型一致。
  • return后面也可以不带参数,不带参数就是返回空,其实主要目的就是用于想中断函数执行,返回调用函数处。

break语句的作用:

  • break在循环体内,强行结束循环的执行,也就是结束整个循环过程,不在判断执行循环的条件是否成立,直接转向循环语句下面的语句。
  • 当break出现在循环体中的switch语句体内时,其作用只是跳出该switch语句体。

方法名

遵守java中标示符的命名规则即。

参数列表

根据需求定义,方法可以是无参的,也可以有一个参数,也可以有多个参数。

异常抛出类型

如果方法中的代码在执行过程中,可能会出现一些异常情况,那么就可以在方法上把这些异常声明并抛出,也可以同时声明抛出多个异常,使用逗号隔开即可。

2.方法的调用

在类中定义了方法,这个方法中的代码并不会执行,当这个方法被调用的时候,方法中的代码才会被一行一行顺序执行。

非静态方法

没有使用static修饰符修饰的方法,就是非静态方法。

调用这种方法的时候一定要使用对象,因为非静态方法是属于对象的。(包括非静态属性)

静态方法

使用static修饰符修饰的方法就是静态方法。

调用这种方法的时候可以使用对象调用,也可以使用类来调用,今天方法是属于类的。(包括静态属性)

类中方法之间的调用

假设同一个类中有两个方法,a方法和b方法:

a和b都是非静态方法,相互之间可以直接调用。

a和b都是静态方法,相互之间可以直接调用。

a是静态方法,b是非静态方法,a方法中不能直接调用b方法,但是b方法中可恶意直接调用a方法。静态方法不能调用非静态方法。

同一个类中静态方法内不能直接访问到类中的非静态属性

3.调用方法时的传参

**形参:**参数列表中的参数为形参

**实参:**调用方法时传递的参数为实参

**值传递:**如果参数的类型是基本数据类型,那么就是值传递。值传递是实参把自己变量本身存的简单数值赋值给形参。

**引用传递:**如果参数的类型是引用数据类型,那么就是引用传递。引用传递是实参把自己变量本身存的对象内存地址值赋值给形参。

4.this关键字

this在类中的作用

  • 区别成员变量和局部变量
  • 调用类中的其他方法
  • 调用类中的其他构造器

this在类中的意义

this在类中表示当前类将来创建出的对象。

创建与初始化对象

使用new关键字创建对象

  • 为对象分配内存空间,将对象的实例变量自动初始化默认值为0/false/null。
  • 如果代码中实例变量有显示赋值,那么就将之前的默认值覆盖掉。(把对象内存地址赋值给变量)
  • 调用构造器。

构造器

类中的构造器也称为构造方法,是在进行创建对象的时候必须调用的。

构造器特点:

  • 必须和类的名字相同
  • 必须没有返回值,也不能写void

构造器的作用:

  • 使用new创建对象的时候必须使用类的构造器
  • 构造器中的代码执行后,可以给对象中的属性初始化赋值

构造器重载:

除了无参构造器之外,我们还会使用有参构造器,在创建对象的时候可以给属性赋值。

构造器之间的调用:

使用this关键字,在一个构造器中可以调用另一个构造器的代码。

this这种用法不会产生新的对象,一般情况下只有使用new关键字才会创建新对象。

默认构造器:

在Java中,即使我们在编写类的时候没有写构造器,那么在编译之后也会自动添加一个无参构造器,这个无参构造器被称作默认的构造器。

内存分析

堆:

  • 存放new的对象和数组
  • 可以被所有的线程共享
  • 一个不连续的内存空间,分配灵活,速度慢

栈:

  • 存放基本变量类型(包含这个基本类型的具体数值)
  • 引用对象的变量(会存放这个引用在堆里面的具体地址)
  • 线程私有,不能实现线程之间的共享
  • 由系统自动分配,是一个连续的内存空间,速度快

方法区:

  • 被所有线程共享
  • 存放类代码信息,静态变量,字符串常量

封装

1.封装的步骤

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

2.封装的作用和意义

  • 提高程序的安全性,保护数据
  • 隐藏代码的实现细节
  • 统一用户的调用接口
  • 提高系统的可维护性
  • 便于调用者调用

3.方法的重载

条件:

  • 同一个类中
  • 方法名相同
  • 参数列表不同(参数的类型,个数,顺序的不同)
  • 方法的返回值可以相同也可以不同

Java中,判断一个类中的两个方法是否相同主要参考方法名字和参数列表

继承

1.继承

  • 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
  • 继承关系的俩个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。
  • 子类和父类之间,从意义上讲应该具有"is a"的关系。
  • 类和类之间的继承是单继承。
  • 类和类之间的继承是单继承

注意

  • 父类中的属性和方法使用public修饰在子类中继承后可以直接使用
  • 父类中的属性和方法使用private修饰在子类中继承后不可以直接使用
  • 父类中的构造器是不能被子类继承的,但是子类的构造其中会隐式的调用父类中的无参构造器(默认使用super关键字)。

2.Object类

Java中的每一个类都是"直接" 或者 "间接"的继承了Object类,所以每一个对象都和Object类有"is a"的关系。从API文档中,可以看到任何一个类最上层的父类都是Object。(Object类本身除外)AnyClass is a Object。

在Object类中,提供了一些方法被子类继承,那么就意味着,在java中,任何一个对象都可以调用这些被继承过来的方法。(因为Object是所以类的父类)
例如:toString方法、equals方法、getClass方法等。
注:Object类中的每一个方法之后都会使用到。

3.super关键字

子类继承父类之后,在子类中可以使用this来表示访问或调用子类中的属性或方法,使用super就表示访问或调用父类中的属性和方法。

super的使用

  • 访问父类中的属性
  • 调用父类中的方法
  • 调用父类中的构造器
  • 显示的调用父类的有参构造器

super使用注意的地方

  • 用super调用父类构造方法,必须是构造方法中的第一个语句。
  • super只能出现在子类的方法或者构造方法中。
  • super和this不能同时调用构造方法(因为this也是在构造方法的第一个语句)。

super和this的区别

  • 代表的事物不一样
    • this:代表所属方法的调用对象
    • super:代表父类对象的引用空间
  • 使用前提不一致
    • this:在非继承的条件下也可以使用
    • super:只能在继承的条件下才能使用
  • 调用构造方法
    • this:调用本类的构造方法
    • super:调用父类的构造方法

4.方法重写

条件

  • 存在继承关系
  • 方法名和参数列表必须跟父类是一致的
  • 子类的权限修饰符必须要大于或等于父类的权限修饰符(private<default<protected<public)
  • 子类的返回值烈性必须小于或者等于父类的返回值类型
  • 子类的异常类型必须要小于或者等于父类的异常类型

注意

  • 静态方法不能重写
    • 父类的静态方法不能被子类重写为非静态方法(编译出错)
    • 父类的非静态方法不能被子类重写为静态方法(编译出错)
    • 子类可以定义与父类的静态方法同名的静态方法(但是不覆盖)
  • 私有方法不能重写

多态

1.多态

  • 一个对象的实际类型是确定的, 可以指向对象的引用的类型有很多。
  • 子类继承父类,调用a方法,如果a方法在子类中没有重写,那么就是调用的是子类继承父类的a方法,如果重写了,那么调用的就是重写之后的方法。

2.重写、重载和多态的关系

重载是编译时多态

调用重载的方法,在编译期间就要确定调用的方法是谁,如果不能确定则编译报错

重写是运行时多态

调用重写的方法,在运行期间才能确定这个方法到底是哪个对象中的。这个取决于调用方法的引用,在运行期间所指向的对象是谁,这个引用指向哪个对象那么调用的就是哪个对象中的方法(Java中的方法调用,是运行时动态和对象绑定的)。

3.多态的注意事项

  • 多态是方法的多态,属性没有多态性
  • 编写程序时,如果想地道用运行时类型的方法,只能进行类型转换。不然通不过编译器的检查。
  • 多态的存在要有三个必要条件:继承,方法重写,父类引用指向子类对象

4.多态存在的条件

  • 继承关系
  • 子类重写父类方法
  • 父类引用指向子类对象

注意

以下三种类型的方法无法表现出多态特性(因为不能被重写):

  • static方法,因为被static修饰的方法是属于类的,而不是属于实例的
  • final方法,因为被final修饰的方法无法被子类重写
  • private方法,因为被private修饰的方法对子类不可见
  • protected方法,因为尽管被protected修饰的方法可以被子类见到,也可以被子类重写,但是它是无法被外部所引用的

5.方法绑定

执行调用方法时,系统根据相关信息,能够执行内存地址中代表该方法的代码。分为静态绑定和动态绑定。

静态绑定

在编译期完成,可以提高代码执行速度

动态绑定

通过对象调用的方法,采用动态绑定机制。这虽然让我们编程灵活,但是降低了代码的执行速度。这也是JAVA比C/C++速度慢的主要因素之一。JAVA中除了final类、final方、static方法,所有方法都是JVM在运行期才进行动态绑定的。

如果编译时类型和运行时类型不一致,就会造成多态

6.instanceof和类型转换

  • 父类引用可以指向子类对象,子类引用不能指向父类对象。
  • 把子类对象直接赋给父类引用叫upcasting向上转型,向上转型不用强制转型。
    如Father father = new Son();
  • 把指向子类对象的父类引用赋给子类引用叫向下转型(downcasting),要强制转型。
    如father就是一个指向子类对象的父类引用,把father赋给子类引用son 即Son son =(Son)father;
  • upcasting 会丢失子类特有的方法,但是子类overriding 父类的方法,子类方法有效
  • 向上转型的作用,减少重复代码,父类为参数,调有时用子类作为参数,就是利用了向上转型。这样使代码变得简洁。体现了JAVA的抽象编程思想。

修饰符

1.static修饰符

静态变量

在类中,使用static修饰的成员变量,就是静态变量,反之为非静态变量。

  • 静态变量属于类的,可以使用类名来访问,非静态变量是属于对象的,必须使用对象来访问
  • 静态变量对于类而言在内存中只有一个,能被类的所有实例所共享。实例变量对于类的每个实例都有一份,它们之间互不影响。
  • 在加载类的过程中为静态变量分配内存,实例变量在创建对象时分配内存,所以静态变量可以使用类名来直接访问,而不需要使用对象来访问。

静态方法

在类中,使用static修饰的成员方法,就是静态方法,反之为非静态方法。

  • 静态方法不可以直接访问类中的非静态方法和非静态变量,但是可以直接访问类中的静态变量和静态方法。(this和super在类中属于非静态的变量)
  • 非静态方法可以直接访问类中的非静态变量和非静态方法,也可以直接访问类中的静态变量和静态方法。
  • 父类的静态方法可以被子类继承,但是不能被子类重写
  • 父类的非静态方法不能被子类重写为静态方法

代码块(匿名代码块)和静态代码块

  • 代码块:在创建对象的时候自动执行,并且在构造器执行之前,同时代码块会在每次创建对象的时候都会自动执行。
    • 作用:给对象的成员变量初始化赋值,但是因为构造器也能完成这项工作,所以匿名代码块使用的并不多。
  • 静态代码块:在类加载完成之后自动执行,并且只执行一次。
    • 是给类中的静态成员变量初始化赋值。

在构造器中给静态变量赋值,并不能保证能赋值成功,因为构造器是在创建对象的时候才指向,但是静态变量可以不创建对象而直接使用类名来访问

创建和初始化过程

  • 类加载,同时初始化类中静态的属性
  • 执行静态代码块
  • 分配内存空间,同时初始化非静态的属性(赋默认值,0/false/null)
  • 调用父类构造器
  • 对子类中的属性进行显示赋值(如果有的话)
  • 执行匿名代码块
  • 执行构造器
  • 返回内存地址

静态导入

静态导包就是java包的静态导入,用import static代替import静态导入包是JDK1.5中的新特性。意思是导入这个类里的静态方法。
好处:这种方法的好处就是可以简化一些操作,例如打印操作System.out.println(…);就可以将其写入一个静态方法print(…),在使用时直接print(…)就可以了。但是这种方法建议在有很多重复调用的时候使用,如果仅有一到两次调用,不如直接写来的方便。

2.final修饰符

修饰类

不能被继承,没有子类。

修饰方法

可以被继承,但是不能被子类的重写。

修饰变量

用final修饰的变量表示常量,只能被赋一次值。

3.abstract修饰符

abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法。如果修饰类,那么该类就是抽象类。

抽象类和抽象方法的关系

抽象类中可以没有抽象方法,但是有抽象方法的一定要声明为抽象类。

特点及作用

  • 抽象类:不能使用new关键字来创建对象,它是用来让子类继承的。
  • 抽象方法:只有方法的声明,没有方法的实现,它是用来让子类实现的。
  • 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。

接口

1.接口

普通类:只有具体实现

抽象类:具体实现和规范(抽象方法)都有

接口:只有规范

2.接口和抽象类的区别

  • 抽象类关键字为abstract,接口关键字为interface
  • 接口中的变量是静态常量,默认使用public static final修饰
  • 接口中不能有构造方法,但是抽象类中可以有
  • 接口中的方法全部都是抽象的(jdk1.8之后可以有静态方法和默认方法),抽象类中可以定义抽象、静态、实例方法
  • 抽象类可以实现多个接口,但是接口不能继承抽象类
  • 接口可以继承多个接口,但是抽象类和抽象类之间只能是单继承
  • 一个类只能继承一个抽象类,但是可以实现多个接口
  • 实现类和接口之间是has a的关系,子类和抽象类之间是is a的关系

内部类

内部类就是在一个类的内部在定义一个类,内部类不是在一个java源文件中编写俩个平行的俩个类,而是在一个类的内部再定义另外一个类。 我们可以把外边的类称为外部类,在其内部编写的类称为内部类。

内部类分为四种:

  • 成员内部类
  • 静态内部类
  • 局部内部类
  • 匿名内部类

标签:调用,静态方法,对象,子类,多态,面向对象,抽象类,父类,方法
来源: https://blog.csdn.net/weixin_49071020/article/details/111082494

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有