Lazy loaded image
编程
📕Day07-面向对象1(类和对象)
字数 7599阅读时长 19 分钟
2019-1-19
2025-8-13
type
status
date
slug
summary
tags
category
icon
password

Java面向对象的三条主线

1、java类以及类的成员:属性、方法、构造器、代码块、内部类
2、面向对象三特征:封装、继承、多态、抽象(可选)
3、其他关键字:this、super、static、final、abstract、interface、package、import等

面向过程vs面向对象

面向过程,强调的是功能行为,以函数为最小单位,考虑怎么做。 面向对象ObjectOrientedProgramming,将功能封装进对象,强调具备了所能的对象,以类/对象为最小单位,考虑谁来做。更强调运用。

类与对象

类:对一类事物的描述,是抽象的、概念上的定义。 对象:实际存在的该类事物的每个个体 面向对象程序设计的重点是类的设计,设计类就是设计类的成员 属性、成员变量、field、域、字段概念类似 。 方法、成员方法、函数、method概念类似
如果创建了一个类的多个对象,则每个对象都独立的拥有了这个类的一套属性,修改一对象的属性a,不影响另一个对象属性a的值。
面向对象的核心: 使用类创建对象!

万事万物皆对象

在java语言的中,我们都将功能、结构封装到一个类中,然后通过类的实例化来调用具体的功能结构。后面学的各种内部类在和前后端数据库交互的时候,在语言层面都体现为类、对象的交互。

声明类的语法

[public] class 类名 { }
类名要遵守大驼峰命名法,每个单词的首字母都大写
一个 .java文件里,可以定义多个类,不建议这样写,最好一个 .java文件就写一个类 如果一个 .java文件里,定义了多个类,最多只有一个类可以被 public 修饰 而且被 public 修饰的类名必须要和文件名一模一样

对象的内存解析

notion image

对象数组的内存解析

notion image

匿名对象

创建的对象,没显式的赋给一个变量名。即为匿名对象,该对象只能调用一次

JVM内存结构图

我们使用JVM中的类的加载器和解释器对生成的字节码文件进行解释运行。意味着,需要将字节码文件对应的类加载到内存中,涉及到内存解析。
notion image
虚拟机栈,即为平时提到的栈结构。我们将局部变量存储在栈结构中 堆,我们将new出来的结构(比如:数组、对象)加载在堆空间中。补充:对象的属性(非static的)加载在堆空间中。 方法区:类的加载信息、常量池、静态域

成员变量、局部变量概念

成员变量: 定义在类里方法外的变量 局部变量: 定义在方法里的变量

作用域

作用域: 变量能够被访问的区域 全局作用域: 在当前类范围,定义在全局作用域里的变量,我们称之为成员变量或者全局变量 局部作用域: 在局部能够访问, 方法作用域和块级作用域

成员变和局部变量的异同

不同点:
  1. 定义的位置不同:属性直接定义在类的一对{}内,局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量。
  1. 权限修饰符不同:属性可以在声明属性时,指明其权限,使用权限修饰符,局部变量不可以使用权限修饰符
  1. 默认值不同: 成员变量如果不赋值,有默认值,默认值由成员变量的类型来决定 byte/short/int/long -->0 float/double-->0.0 char->空字符 boolean->false 引用数据类型-->null 局部变量如果不赋值,不能使用,我们在调用局部变量之前,一定要显式赋值。
  1. 内存中加载的位置不同 非static的属性加载到堆空间中,局部变量加载在栈空间中
  1. 作用域不同: 成员变量在整个当前类里都可以访问 局部变量只能在声明这个变量的方法里才能访问
  1. 存储的位置不同: 成员变量存储在堆区的对象里;局部变量存在在栈区里
  1. 生命周期不同: 成员变量随着对象的创建而创建,对象销毁时销毁; 局部变量是在方法执行时创建,方法执行完成以后就销毁
相同点:
  1. 定义变量的格式相同 数据类型 变量名 = 变量值
  1. 先声明,后使用
  1. 变量都有作用域
  1. 都可以被final关键字修饰为常量
 

回顾变量的分类

按照数据类型
notion image
按照在类中声明的位置
notion image

static

static关键字可以用来修饰变量和方法
被static修饰的变量属于类,在类里保存一份(加载在方法区),实例对象中没有单独保存数据 非静态成员变量在方法区的类里,没有存储数据,只有属性的声明,值存储在堆区的实例对象里。 被static修饰的属性可以通过类或者实例对象来访问!
静态方法只能访问静态属性和调用静态方法,不能访问非静态属性,也不能调用非静态方法! 原因:静态方法可以不创建实例对象,直接通过类调用

封装方法

相同的代码在不同的地方重复出现多次,导致代码冗余,同时代码维护性很低此时可以考虑将重复的多段代码抽取出来,当做一个整体放入到一个方法里在适当的位置调用这个方法

方法的三要素

  1. 权限修饰符
  1. 返回值类型:表示该方法执行完成以后,是否有结果以及结果的类型
  1. 方法名: 给方法起的名字,命名要遵守命名规范 遵守小驼峰命名法,同时要做到顾名思义(通常使用动词 或者 动词+名词) sleep() / eat() / tellStory() / setName() / getName()
  1. 形参: () 里的参数我们称之为形式参数,只起到占位的作用,用来保证逻辑的完整性,如果方法声明时,需要形参,方法调用时,就必须要传入实参(实际参数),方法调用时,传入的实参个数、类型 要 和 方法声明时的形参 个数、类型匹配

方法的注意事项

  1. 方法只能声明在类里,方法外,不能声明在另一个方法中
  1. 方法的声明 [public] [static] 返回值类型 方法名(参数1,参数2...参数列表) { 方法体; }
  1. 方法的调用: 方法名(参数1,参数2...参数列表); 方法调用时,传入的参数是实参,实参是参与逻辑运算真正的值。

Java的值传递机制

规则: 如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值 如果参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值
换句话说: 如果变量是基本数据类型,此时赋值的是变量所保存的数据值。 如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。

值传递内存解析

notion image

方法参数的使用

return

返回值类型,如果方法有返回值,则必须在方法声明时候,指定返回值的类型,同时方法中需要return关键字类返回指定类型的变量和常量 如果没有返回值,则方法声明的时候,需要使用void来表示返回类型,在没有返回值的方法中,可以不使用return关键字,如果使用的话,只能用return,不能加其他返回类型; 定义方法该不该有返回值:1看要求,2具体情况具体分析
return关键字后面不可以声明执行语句。

return关键字的作用

  1. return 只能用于方法里,用来表示方法的执行以后返回的结果
  1. 当方法声明时,返回值类型是void, return 后面也可以不返回任何的内容,表示结束一个方法,return 用来表示一个方法的结束
  1. return后面不能再有任何的语句,因为都无法被执行到。
  1. 一个方法可以有多个return语句,但是通常情况下,最多只会执行其中的一个return语句 特殊情况下(finally语句条件下),一个方法的多个 return语句都会被执行!

方法的重载

在 Java里允许出现一以上的的同名方法。
两同一不同 两同:同一个类中,方法名相同 一不同:参数不同,具体的表现如下,满足1个就构成重载: 1. 参数的类型不同 2. 参数的个数不同 3. 参数的顺序不同 方法是否重载,只和参数有关! 与跟方法的权限修饰符、返回值类型、形参变量名、方法体无关。
重载也会适用自动类型提升

可变个数的形参

jdk5.0新增的内容
该机制允许直接定义能和多个实参相互匹配的形参,从而可以用一种更灵活的方式,来传递个数不固定实参。可变个数形参的方法与本类中方法名相同、形参不同的方法之间构成重载。 可变类型形参的方法和数组方法名相同、形参类型也相同的数组不构成重载,String ... strs和String[] strs是相同的。并且二者不能共存 可变个数的形参只能写在形参的最后一位,且在形参列表中只能存在一个 一个方法,最多只能声明一个可变形参 使用场景:数据库查询where条件后的

递归方法

递归方法:一个方法体内调用它自身。
递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。
递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。

递归练习题

 

封装

面向对象的三大特征: 封装、继承和多态。
当我们创建一个类的对象以后,我们可以通过“对象.属性”的方式,对对象的属性进行赋值,但在实际问题中,我们可能需要给属性赋值加入额外限制条件。限制条件的添加需要通过方法,同时我们需要避免用户在使用“对象.属性”来对属性进行赋值,则需要将属性声明为私有的。此时,针对于属性就体现了封装性。
封装追求高内聚和低耦合,隐藏了对象内部的复杂性,只对外公开简单的接口,便于外界调用,从而提供了系统的可扩展、可维护性。
封装性的体现:需要权限修饰符来配合。 1.java规定4种权限修饰符:private、缺省(什么都不写)、protected、public。 2.四种权限可以用来修改类和类的内部结构:属性、方法、构造器、内部类 3.具体的,4中权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类;修饰类的话,只能使用:缺省、public

引入封装的必要性

  • 程序设计追求高内聚低耦合 高内聚 :类的内部数据操作细节自己完成,不允许外部干涉; 低耦合 :仅对外暴露少量的方法用于使用
  • 隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。通俗的说,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。

封装性的代码体现

  1. 将类的属性xxx私化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)此属性的值
  1. 不对外暴露的私有的方法
  1. 单例模式(将构造器私有化)
  1. 如果不希望类在包外被调用,可以将类设置为缺省的。

this调用属性、方法

this表示的是,哪个对象调用了这个方法,方法里的this就表示这个对象 大部分情况下,方法里的this都可以省略,但是如果在方法里出现了和成员变量同名的局部变量,此时若直接写变量名,访问的是方法里的局部变量;如果想要访问成员变量,this不能省略
同理,在类的构造器中,可以使用"this.属性"或"this.方法"的方式,调用当前正在创建的对象属性或方法。通常情况下都择省略"this."。但是如果构造器的形参和类的属性同名时,我们必须显式的使用"this.变量"的方式,表明此变量是属性,而非形参。

this修饰和调用构造器

  1. 我们在类的构造器vs,可以显式的使用“this(形参列表)”,来调用本类中的其他构造器
  1. 构造器中不能通过“this(形参列表)”来调用自己,也不能互相调用,不能造成循环,最后一个什么没有写的其实也在调用,是调用其父类,后面会学super,进行进一步了解
  1. 构造器的反复调用,只是造了一个对象,如果一个类中又n个构造器,则最多有n-1构造器中使用了“this(形参列表)”
  1. this(形参列表)必须放在构造器内容的首行,规定,不然会报错。
  1. 构造器内部最多声明一个“this(形参列表)”用来调用构造器,同④

构造器

构造方法也叫构造器 构造方法是一个特殊形式的方法,特殊在:
  1. 方法的名字和类名一模一样!
  1. 构造方法不能有返回值类型声明,也不能使用 return语句返回结果
  • 构造器的作用
  1. 创建对象 new + 构造器
  1. 初始化对象的属性
  • 构造器使用说明
  1. 如果没显式的定义类的构造器的话,则系统默认提供一个空参的构造器
  1. 定义构造器的格式:权限修饰符 类名(形参列表){}
  1. 一个类中定义的多个构造器,彼此构成重载
  1. 一旦我们显式的定义了类的构造器之后,系统就不再提供默认的空参构造器
  1. 一个类中,至少会有一个构造器。

构造器注意事项

  1. 如果没有显式的定义类的构造器的话,系统就会提供一个空参的构造器
  1. 定义构造器的格式,权限修饰符 类名(形参列表)
  1. 构造器也可以重载
  1. 一旦我们显式的定义了类的构造器之后, 系统就不再提供默认的空参构造器了。结合老师说的例子,挣不了钱的时候,政府会有补贴,但是一旦能够自食其力了, 国家就不会在发钱了。
  1. 一个类中,至少要有一个构造器,可能是默认或者是自己写的,类一定是有构造器的。
 

Java Bean

符合以下标准的Java类
  1. 类是公共的
  1. 有一个无参的公共构造器
  1. 有属性,且有对应的get、set方法
用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以用Java代码创建的对象进行打包,并且其他的开发者也可以通过内部的JSP页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象.
可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关心任何改变
上一篇
Day06-二维数组和方法
下一篇
Day08-面向对象2(封装习题)