4. 面向对象编程(上)

一、Java面向对象学习的三条主线

  1. Java类及类的成员:属性、方法、构造器;代码块、内部类

  2. 面向对象的三大特征:封装性、继承性、多态性、(抽象性)

  3. 其它关键字:this、super、static、final、abstract等

面向过程(POP): 强调的是功能行为,以函数为最小单位,考虑怎么做

面向对象(OOP): 强调具备了功能的对象,以类/对象为最小单位,考虑谁来做

Java语言的基本元素: 类和对象 (类是对象的模板,对象是类的实例)
类(Class)和对象(Object)是面向对象的核心概念。

类是对一类事物的描述,是抽象的、概念上的定义
对象是实际存在的该类事物的每个个体,因而也称为实例(instance)。

面向对象程序设计的重点是类的设计

类的设计,其实就是类的成员的设计

属性 = 成员变量 = field = 域、字段

方法 = 成员方法 = 函数 = method

创建类的对象 = 类的实例化 = 实例化类

类和对象的使用

  1. 创建类,设计类的成员
  2. 创建类的对象
  3. 通过“对象.属性”或“对象.方法”调用对象的结构

如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性。(非static的)

类的语法格式

修饰符 class 类名 { 
            属性声明;
            方法声明; 
}
 说明:修饰符public:类可以被任意访问;类的正文要用{ }括起来

对象的创建和使用

Java类的实例化,即创建类的对象
创建对象语法: 类名 对象名 = new 类名();
使用“对象名.对象成员”的方式访问对象成员(包括属性和方法)

类的访问机制:

  1. 在一个类中的访问机制:类中的方法可以直接访问类中的成员变量。
    (例外:static方法访问非static,编译不通过。)
  2. 在不同类中的访问机制:先创建要访问类的对象,再用对象访问类中 定义的成员。
3f09d65c777d355148558931fc9f83da.png

引用类型的变量,只可能存储两类值:null 或 地址值(含变量的类型)

匿名对象:

不定义对象的句柄,而直接调用这个对象的方法。这样的对象叫做匿名对象。 如:new Person().shout();
特征:匿名对象只能调用一次
使用情况 :

  1. 如果对一个对象只需要进行一次方法调用,那么就可以使用匿名对象。
  2. 我们经常将匿名对象作为实参传递给一个方法调用。

JVM内存结构:
编译完源程序以后,生成一个或多个字节码文件。我们使用JVM中的类的加载器和解释器对生成的字节码文件进行解释运行。意味着,需要将字节码文件对应的类加载到内存中,涉及到内存解析。

类的成员之一:属性

语法格式: 修饰符 数据类型 属性名 = 初始化值 ;
说明1: 修饰符

  • 常用的权限修饰符有:private、缺省、protected、public
  • 其他修饰符:static、final (暂不考虑)

说明2:数据类型

  • 任何基本数据类型(如int、Boolean) 或 任何引用数据类型。

说明3:属性名

  • 属于标识符,符合命名规则和规范即可。
88a4d7eb41049e67c5a1e212d6c87977.png

属性 vs 局部变量

  1. 相同点:

    • 定义变量的格式:数据类型 变量名 = 变量值
    • 先声明,后使用
    • 变量都有其对应的作用域
  2. 不同点:

    • 2.1 在类中声明的位置的不同

      • 属性:直接定义在类的一对{}内
      • 局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量
    • 2.2 关于权限修饰符的不同

      • 属性:可以在声明属性时,指明其权限,使用权限修饰符。
        * 常用的权限修饰符:private、public、缺省、protected --->封装性
      • 局部变量:不可以使用权限修饰符。
    • 2.3 默认初始化值的情况:

      • 属性:类的属性,根据其类型,都有默认初始化值。
        * 整型(byte、short、int、long):0
        * 浮点型(float、double):0.0
        * 字符型(char):0 (或'\u0000')
        * 布尔型(boolean):false
        * 引用数据类型(类、数组、接口):null
      • 局部变量:没有默认初始化值。
        * 意味着,我们在调用局部变量之前,一定要显式赋值。
        * 特别地:形参在调用时,我们赋值即可。
    • 2.4 在内存中加载的位置:

      • 属性:加载到堆空间中 (非static)
      • 局部变量:加载到栈空间

类的成员之一:方法

方法是类或对象行为特征的抽象,用来完成某个功能操作。在某些语言中 也称为函数或过程。
将功能封装为方法的目的是,可以实现代码重用,简化代码
Java里的方法不能独立存在,所有的方法必须定义在类里。

5da2d55855312bc1ba5474cf790863da.png
  • 返回值类型: 有返回值 vs 没有返回值
    • 如果方法有返回值,则必须在方法声明时,指定返回值的类型。同时,方法中,需要使用return关键字来返回指定类型的变量或常量:“return 数据”。
    • 如果方法没有返回值,则方法声明时,使用void来表示。通常,没有返回值的方法中,就不需要使用return。但是,如果使用的话,只能“return;”表示结束此方法的意思。
  • return关键字的使用:
    1.使用范围:使用在方法体中
    2.作用:
    • 结束方法
    • 针对于有返回值类型的方法,使用"return 数据"方法返回所要的数据。
  1. 注意点:return关键字后面不可以声明执行语句。

方法的使用中,可以调用当前类的属性或方法
特殊的:

  • 方法A中又调用了方法A:递归方法。
  • 方法中,不可以定义方法。

方法重载

定义:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
跟方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系

"两同一不同":

  • 同一个类、相同方法名
  • 参数列表不同:参数个数不同,参数类型不同(甚至参数类型的顺序不同也允许)

可变个数形参

//JDK 5.0以前:采用数组形参来定义方法,传入多个同一类型变量 
public static void test(int a ,String[] books); 
//JDK5.0:采用可变个数形参来定义方法,传入多个同一类型变量 
public static void test(int a ,String...books);
以上两种不算方法重载,是可变个数形参的两种写法

说明 :

  1. 声明格式:方法名(参数的类型名 ...参数名)
  2. 可变参数:方法参数部分指定类型的参数个数是可变多个:0个,1个或多个
  3. 可变个数形参的方法与同名的方法之间,彼此构成重载
  4. 可变参数方法的使用与方法参数部分使用数组是一致的
  5. 方法的参数部分有可变形参,需要放在形参声明的最后
  6. 在一个方法的形参位置,最多只能声明一个可变个数形参
//关于对内部参数的调控和数组一致
public void show(String ... strs){
        System.out.println("show(String ...  strs)");
        for(int i = 0;i < strs.length;i++){
            System.out.println(strs[i]);
        }
    }

方法参数的值传递机制

  • 关于变量的赋值:

    • 如果变量是基本数据类型,此时赋值的是变量所保存的数据值。
    • 如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。
  • 方法,必须由其所在类或对象调用才有意义。若方法含有参数:

    • 形参:方法声明时的参数
    • 实参:方法调用时实际传给形参的参数值

Java里方法的参数传递方式只有一种:值传递。即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。

  • 值传递机制:
    • 如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值。
    • 如果参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值。

递归方法

即在一个方法体内调用它自身。

  • 方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。
  • 递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。
//计算1-num之间所有自然数的和 
public int num(int num){ 
    if(num == 1){ 
       return 1; 
    }else{ 
       return num + sum(num - 1); 
  } 
}

面向对象特征之一: 封装与隐藏

引入:在实际问题中,我们往往需要给属性赋值加入额外的限制条件。这个条件就不能在属性声明时体现,我们只能通过方法进行限制条件的添加。

封装性的体现:

  • 我们将类的属性xxx私有化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)此属性的值
  • 拓展:封装性的体现:① 如上 ② 不对外暴露的私有的方法 ③ 单例模式 ...

封装性的体现,需要权限修饰符来配合。

  1. Java规定的4种权限(从小到大排列):private、缺省(default)、protected 、public
  2. 4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类
    修饰类的话,只能使用:缺省、public
53eb0a71fcf68166824826b7efb01fc9.png

类的成员之三: 构造器(或构造方法)

一、构造器的作用:

  1. 创建对象
  2. 初始化对象的信息

例如: Order o = new Order();Order()即是调用了构造器

二、构造器的特征 :

  1. 它具有与类相同的名称
  2. 它不声明返回值类型。(与声明为void不同)
  3. 不能被static、final、synchronized、abstract、native修饰,不能有return语句返回值

三、说明:

1.如果没有显式的定义类的构造器的话,则系统默认提供一个空参的构造器
2.定义构造器的格式:权限修饰符 类名(形参列表){}
3.一个类中定义的多个构造器,彼此构成重载
4.一旦我们显式的定义了类的构造器之后,系统就不再提供默认的空参构造器
5.一个类中,至少会有一个构造器。
6.父类的构造器不可被子类继承

四、类属性赋值的先后顺序

  • 默认初始化 (int age;)
  • 显式初始化 (int age=10;)
  • 构造器中初始化 (this.age=age;)
  • 通过"对象.方法" 或 "对象.属性"的方式,赋值 (boy.age=10;)

①,②,③只会在对象的创建与初始化中运行一次。

拓展:

  1. JavaBean是一种Java语言写成的可重用组件。
    所谓JavaBean,是指符合如下标准的Java类:
    • 类是公共的
    • 有一个无参的公共的构造器
    • 有属性,且有对应的get、set方法
  2. UML类图
9400841e89a53a9e0da7d690d5899afb.png

关键字:this的使用

this理解为:当前对象 或 当前正在创建的对象

this可以用来修饰、调用:属性、方法、构造器

  • 在类的方法中,我们可以使用"this.属性"或"this.方法"的方式,调用当前对象属性或方法。
    但是,通常情况下,我们都选择省略"this."。
    特殊情况下,如果方法的形参和类的属性同名时,我们必须显式的使用"this.变量"的方式,表明此变量是属性,而非形参。
  • 在类的构造器中,我们可以使用"this.属性"或"this.方法"的方式,调用当前正在创建的对象属性或方法。
    但是,通常情况下,我们都选择省略"this."。
    特殊情况下,如果构造器的形参和类的属性同名时,我们必须显式的使用"this.变量"的方式,表明此变量是属性,而非形参。
  • 使用this访问属性和方法时,如果在本类中未找到,会从父类中查找

this调用构造器

① 我们在类的构造器中,可以显式的使用"this(形参列表)"方式,调用本类中指定的其他构造器
② 构造器中不能通过"this(形参列表)"方式调用自己
③ 如果一个类中有n个构造器,则最多有 n - 1构造器中使用了"this(形参列表)"
④ 规定:"this(形参列表)"必须声明在当前构造器的首行
⑤ 构造器内部,最多只能声明一个"this(形参列表)",用来调用其他的构造器

关键字:package、 import的使用

一、package

  • package语句作为Java源文件的第一条语句,声明类或接口所属的包。(若缺省该语句,则指定为无名包)。它的格式为:package 顶层包名.子包名 ;

包对应于文件系统的目录,package语句中,用 “.” 来指明包(目录)的层次;
包通常用小写单词标识。

补充:

  1. 同一个包下,不能命名同名的接口、类。
  2. 不同的包下,可以命名同名的接口、类。

2821171871813487b1d4bf8d95adfa50.png f1a59b8318cdf4e6db7eea8733316c89.png

二、import

为使用定义在不同包中的Java类,需用import语句来引入指定包层次下所需要的类或全部类(.*)。
import语句告诉编译器到哪里去寻找类。

    1. 在源文件中显式的使用import结构导入指定包下的类、接口(格式:import 包名. 类名;)
    1. 声明在包的声明和类的声明之间
    1. 如果需要导入多个结构,则并列写出即可
    1. 可以使用"xxx.*"的方式,表示可以导入xxx包下的所有结构
    1. 如果使用的类或接口是java.lang包下定义的,则可以省略import结构
    1. 如果使用的类或接口是本包下定义的,则可以省略import结构
    1. 如果在源文件中,使用了不同包下的同名的类,则必须至少有一个类需要以全类名的方式显示。
    1. 使用"xxx.*"方式表明可以调用xxx包下的所有结构。但是如果使用的是xxx子包下的结构,则仍需要显式导入
    1. import static:导入指定类或接口中的静态结构:属性或方法。
posted @ 2023-09-30 16:12  LemonPuer  阅读(16)  评论(0)    收藏  举报