09-面向对象2
Posted liujiaqi1101
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了09-面向对象2相关的知识,希望对你有一定的参考价值。
方法概述
- 方法是类或对象行为特征的抽象,用来完成某个功能操作;将功能封装为方法的目的是,可以实现代码重用,简化代码
- Java中的方法只能作为类的一部分来创建,即Java里的方法不能独立存在,所有的方法必须定义在类里
- 方法只有通过对象才能被调用,且这个对象必须能执行这个方法调用
- 如果试图在某个对象上调用它并不具备的方法,那么在编译时就会得到一条错误信息
- 这种调用方法的行为通常被称为"发送消息给对象"
- 方法的基本组成部分:名称、参数、返回值、方法体
- 4种权限修饰符:private、public、缺省、protected
- 返回类型描述的是在调用方法之后从方法返回的值;返回类型必须要与接收变量的类型兼容
- 参数列表给出了要传给方法的信息的类型和名称;如果传递类型是对象,那么这里实际传递的是个引用
- 方法名和参数列表(合起来称为"方法签名")唯一地标识出某个方法
- return
- 作用
- 导致当前方法退出
- 针对有返回值的方法,使用
return ____;
的方式返回数据
- Tips
- 如果在返回void的方法中没有return语句,那么在该方法的结尾处会有一个隐式的
return;
- 在方法中并非总是必须要有一个return语句
- 没有必要到方法结束时才离开,可在任何地方return
return语句
之后不可再写别的语句,编译会报错
- 如果在返回void的方法中没有return语句,那么在该方法的结尾处会有一个隐式的
- 作用
- 方法的分类:按照是否有形参及返回值
- 方法的调用
- 方法通过方法名被调用,且只有被调用才会执行
- 方法调用的过程分析
方法重载
引入
同名的方法通过所给的不同的形参做类似的事情
区别重载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)
- 参数个数不同:
- 方法重载和方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系!
涉及基本类型的重载
- 如果传入的数据类型(实际参数类型) 小于 方法中声明的形式参数类型,实际数据类型就会被提升
- 基本类型能从一个"较小"的类型自动提升至一个"较大"的类型
- char型如果无法找到恰好接受char参数的方法,就会把char直接提升至int
- 如果传入的数据类型(实际参数类型) 大于 方法中声明的形式参数类型
- 传入前,要先对实参进行强制类型转换
- 如果不这么做,编译器就会报错
可变个数的形参
- JDK5 中提供了Varargs(variable number of arguments)机制,允许直接定义能和多个实参相匹配的形参。从而可以用一种更简单的方式,来传递个数可变的实参
- 格式(参数可以是0个或多个)
- 可变形参的方法与本类中方法名相同,形参不同的方法可以构成重载
- 可变个数形参的方法与本类中方法名相同,形参类型也相同的数组不构成重载
- 可变参数方法的使用与方法参数部分使用数组是一致的
- 方法的参数部分有可变形参,需要放在形参声明的最后 // must be the last param
- 在一个方法的形参位置,最多只能声明一个可变个数形参
方法参数的值传递机制
Java中不管是值对象还是引用对象都是值传递
- 参数在程序语言中分为形式参数和实际参数
- 形式参数:是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数
- 实际参数:在调用有参函数时,主调函数和被调函数之间有数据传递关系。在主调函数中调用一个函数时,函数名后面括号中的参数称为“实际参数”
- 值传递和引用传递
- 值传递(pass by value):在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数
- 引用传递(pass by reference):在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。把实际参数的引用的地址复制了一份,传递给了形式参数。所以,引用传递实际还是值传递,把实参对象引用的地址当做值传递给了形式参数
- 内存图
- 参数类型为基本数据类型
- 参数类型为引用数据类型
- 方法的参数传递
- 参数类型为基本数据类型
- 打印数组名
递归
简述
- 定义:一个函数直接或间接调用自己
- 函数内部调用别的函数和调用自己没啥区别
- 使用递归解决问题的思路
- [ 规模为n的问题 ] 的解决要借助于 [ 规模为n-1的问题 ] 的解决
- 递归要满足3个条件
- 递归必须有一个明确的中止条件
- 该函数所处理的数据规模必须在递减
- 这个转化必须是可解的
函数调用过程
- 逻辑上
- 内存上
例题-走楼梯
N级台阶,每次可走1步或者2步,求总共有多少种走法?
分析
- 问题本质是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)
代码实现
public class JumpStairTest {
public static void main(String[] args) {
int stairs = 10;
System.out.printf("%d阶台阶共有%d种走法
", 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];
}
}
封装与隐藏
引入
当我们创建一个类的对象以后,通过"对象.属性"的方式,对对象的属性进行赋值,这里的赋值操作仅受到属性的数据类型和存储范围的限制。除此之外,没有其他制约条件。但是,在实际问题中,我们往往需要在给属性赋值时加入额外的限制条件(比如age不能是个负数啊)。为此,只能通过方法给属性赋值来进行限制;同时,避免"对象.属性"赋值,而针对这种情况,Java提供了访问权限修饰符private
- 程序设计追求“高内聚,低耦合”
- 高内聚 :类的内部数据操作细节自己完成,不允许外部干涉
- 低耦合 :仅对外暴露少量的方法用于使用
- 隐藏对象内部的复杂性,仅对外提供公共访问方式;便于外界调用,从而提高系统的可扩展性、可维护性
- 通俗地说,把该隐藏的隐藏起来,该暴露的暴露出来;这就是封装性的设计思想
- "实现隐藏" 就是通过将细节"私有化"把接口和实现分离开来
私有化属性
Java中通过将数据声明为私有的(private),再提供公共的(public)方法:getXxx()和setXxx() 实现对该属性的操作 // 封装性的一个体现
- 隐藏一个类中不需要对外提供的实现细节
- 使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑, 限制对属性的不合理操作
- 便于修改,增强代码的可维护性
访问权限修饰符
- 封装性的体现,需要访问权限修饰符的配合
- Java权限修饰符public、protected、缺省(包访问权限)、private置于类的成员定义前, 用来限定对象对该类成员的访问权限
- 访问方式
- 外部访问:通过 [类名]/[类的对象] 访问类内部的成员
- 内部访问:类内部成员之间的相互访问
- 在一个类的内部,所有的成员可以相互访问,访问控制符是透明的;访问控制符是针对 [外部访问] 而言的
- 访问权限控制的等级(体现类及类的内部结构在被调用时的可见性的大小)
- 4种权限可以用来修饰 {类的内部结构}:属性、方法、构造器、内部类
- 对于 {类} 的权限修饰只可以用 public 和 (缺省)
- public类 可以在任意地方被访问
- default类 只可以被同一个包内部的类访问 // 在其他包下import也没用
以上是关于09-面向对象2的主要内容,如果未能解决你的问题,请参考以下文章