Loading

09-面向对象2

1. 方法概述

  • 方法是类或对象行为特征的抽象,用来完成某个功能操作;将功能封装为方法的目的是,可以实现代码重用,简化代码
  • Java 中的方法只能作为类的一部分来创建,即 Java 里的方法不能独立存在,所有的方法必须定义在类里;方法只有通过对象才能被调用,且这个对象必须能执行这个方法调用。
    • 如果试图在某个对象上调用它并不具备的方法,那么在编译时就会得到一条错误信息
    • 这种调用方法的行为通常被称为"发送消息给对象"
  • 方法的基本组成部分:名称、参数、返回值、方法体
    • 4 种权限修饰符:private、public、缺省、protected
    • 返回类型描述的是在调用方法之后从方法返回的值;返回类型必须要与接收变量的类型兼容
    • 参数列表给出了要传给方法的信息的类型和名称;如果传递类型是对象,那么这里实际传递的是个引用
    • 方法名和参数列表(合起来称为"方法签名")唯一地标识出某个方法
  • return
    • 作用
      • 导致当前方法退出
      • 针对有返回值的方法,使用 return ____; 的方式返回数据
    • Tips
      • 如果在返回 void 的方法中没有 return 语句,那么在该方法的结尾处会有一个隐式的 return;
      • 在方法中并非总是必须要有一个 return 语句
      • 没有必要到方法结束时才离开,可在任何地方 return
      • return语句 之后不可再写别的语句,编译会报错
  • 方法的分类:按照是否有形参及返回值
  • 方法的调用:方法通过方法名被调用,且只有被调用才会执行
  • 方法调用的过程分析

2. 方法重载

2.1 引入

同名的方法通过所给的不同的形参做类似的事情

2.2 区别重载func

  • 通过 [方法名] 和 [参数列表] 区别一个方法
  • 要求重写的方法参数列表不同
    • 参数个数不同:func(int a, int b) & func(int a, int b, int c)
    • 参数数据类型不同:func(double d1, double d2) & func(int a, int b)
    • 参数顺序不同:func(int i, String s) & func(String s, int i)
  • 方法重载和方法的权限修饰符返回值类型形参变量名方法体都没有关系!

2.3 涉及基本类型的重载

  • 如果传入的数据类型(实际参数类型) 小于 方法中声明的形式参数类型,实际数据类型就会被提升
    • 基本类型能从一个"较小"的类型自动提升至一个"较大"的类型
    • char 型如果无法找到恰好接受 char 参数的方法,就会把 char 直接提升至 int
  • 如果传入的数据类型(实际参数类型) 大于 方法中声明的形式参数类型
    • 得通过类型转换来执行强制类型转换
    • 如果不这么做,编译器就会报错

2.4 可变个数的形参

  • JDK5 中提供了 Varargs(variable number of arguments) 机制,允许直接定义能和多个实参相匹配的形参。从而可以用一种更简单的方式,来传递个数可变的实参
  • 格式(参数可以是 0 个或多个)
  • 可变形参的方法与本类中方法名相同,形参不同的方法可以构成重载
  • 可变个数形参的方法与本类中方法名相同,形参类型也相同的数组不构成重载
  • 可变参数方法的使用与方法参数部分使用数组是一致的
  • 方法的参数部分有可变形参,需要放在形参声明的最后 // must be the last param
  • 在一个方法的形参位置,最多只能声明一个可变个数形参

3. 方法参数的值传递机制

Java中不管是值对象还是引用对象都是值传递

  • 参数在程序语言中分为形式参数和实际参数
    • 形式参数:是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数
    • 实际参数:在调用有参函数时,主调函数和被调函数之间有数据传递关系。在主调函数中调用一个函数时,函数名后面括号中的参数称为“实际参数”
  • 值传递和引用传递
    • 值传递(pass by value):在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数
    • 引用传递(pass by reference):在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。把实际参数的引用的地址复制了一份,传递给了形式参数。所以,引用传递实际还是值传递,把「实参对象引用的地址」当做值传递给了形式参数
  • 内存图
    • 参数类型为基本数据类型
    • 参数类型为引用数据类型
    • 方法的参数传递
  • 打印数组名

4. 递归

4.1 简述

  • 定义:一个函数直接或间接调用自己
  • 函数内部调用别的函数和调用自己没啥区别
  • 使用递归解决问题的思路
    • [ 规模为 n 的问题 ] 的解决要借助于 [ 规模为 n-1 的问题 ] 的解决
  • 递归要满足 3 个条件
    • 递归必须有一个明确的中止条件
    • 该函数所处理的数据规模必须在递减
    • 这个转化必须是可解的

4.2 函数调用过程

  • 逻辑上
  • 内存上

4.3 例题-走楼梯

N 级台阶,每次可走 1 步或者 2 步,求总共有多少种走法?

a. 问题分析

  • 问题本质是 Fibonacci 数列
    • 假设只有 1 个台阶,那么只有 1 种跳法,那就是一次跳一级,f(1) = 1
    • 如果有 2 个台阶,那么就有 2 种跳法,①一次跳一级;②一次跳两级,f(2) = 2
  • 如果有 n >= 2 级的 N 阶台阶
    • 假如第一次跳 1 级台阶,剩下还有 n-1 级台阶,有 f(n-1) 种跳法
    • 假如第一次跳 2 级台阶,剩下还有 n-2 级台阶,有 f(n-2) 种跳法
    • 总的来看,就是 f(n) = f(n-1) + f(n-2)

b. 代码实现

public class JumpStairTest {
    public static void main(String[] args) {
        int stairs = 10;
        System.out.printf("%d阶台阶共有%d种走法\n", stairs, recursion(stairs));
        System.out.printf("%d阶台阶共有%d种走法", stairs, dp(stairs));
    }

    // O(N!)
    public static int recursion(int n) {
        if (n == 0 || n == 1 || n == 2) return n;
        return recursion(n-1) + recursion(n-2);
    }

    static int[] dp = new int[20];
    public static int dp(int n) {
        if (n == 0 || n == 1 || n == 2) return n;
        dp[1] = 1;
        dp[2] = 2;
        int i = 3;
        for (; i <= n; i++) dp[i] = dp[i-1] + dp[i-2];
        return dp[--i];
    }
}

5. 封装与隐藏

5.1 引入

当我们创建一个类的对象以后,通过"对象.属性"的方式,对对象的属性进行赋值,这里的赋值操作仅受到属性的数据类型和存储范围的限制。除此之外,没有其他制约条件。但是,在实际问题中,我们往往需要在给属性赋值时加入额外的限制条件(比如 age 不能是个负数啊)。为此,只能通过方法给属性赋值来进行限制;同时,避免 对象.属性 赋值,而针对这种情况,Java 提供了访问权限修饰符 private。

  • 程序设计追求“高内聚,低耦合”
    • 高内聚 :类的内部数据操作细节自己完成,不允许外部干涉
    • 低耦合 :仅对外暴露少量的方法用于使用
  • 隐藏对象内部的复杂性,仅对外提供公共访问方式;便于外界调用,从而提高系统的可扩展性、可维护性
    • 通俗地说,把该隐藏的隐藏起来,该暴露的暴露出来;这就是封装性的设计思想
    • "实现隐藏" 就是通过将细节"私有化"把接口和实现分离开来

5.2 私有化属性

Java 中通过将数据声明为私有的(private),再提供公共的(public)方法:getXxx() 和 setXxx() 实现对该属性的操作 // 封装性的一个体现

  • 隐藏一个类中不需要对外提供的实现细节
  • 使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑, 限制对属性的不合理操作
  • 便于修改,增强代码的可维护性

6. 访问权限修饰符

封装性的体现,需要访问权限修饰符的配合。Java 权限修饰符 public、protected、缺省(包访问权限)、private 置于类的成员定义前, 用来限定对象对该类成员的访问权限。

  • 访问方式
    • 外部访问:通过 [类名]/[类的对象] 访问类内部的成员
    • 内部访问:类内部成员之间的相互访问
  • 在一个类的内部,所有的成员可以相互访问,访问控制符是透明的;访问控制符是针对 [外部访问] 而言的
  • 访问权限控制的等级(体现类及类的内部结构在被调用时的可见性的大小)
  • 4 种权限可以用来修饰 {类的内部结构}:属性、方法、构造器、内部类
  • 对于 {类} 的权限修饰只可以用 public 和 (缺省)
    • public 类可以在任意地方被访问
    • default 类只可以被同一个包内部的类访问 // 在其他包下 import 也没用
posted @ 2020-05-31 12:12  tree6x7  阅读(141)  评论(0编辑  收藏  举报