JavaSE Day06 函数
1.函数存在的意义
函数是主要解决那些重复的具有独立功能的代码段,将这些具有独立功能的代码可以进行再次封装,封装出来的就是函数。就是将函数模块化。
函数模块化优势:降低了代码冗余,复用函数即可,减低主函数的代码量,将主函数进行适当的拆分,以便内存优化。
函数格式
访问权限 函数类型 返回值类型 函数名(参数列表){
函数体
return 返回值;
}
对函数格式的说明
访问权限:指的就是函数的使用范围(内部和外部)public protected 默认 private
函数类型:函数的类型分,就是函数的具体使用场景和场合 类static 静态函数 默认不写 成员函数 abstract 抽象函数 native
本地函数synchronized 同步函数 函数名:程序员给这一段代码自定义的名称(标识符) 参数列表:参数列表由若干个 参数类型,参数名
组成 主要用于外界传递给函数的一些数据。 函数体:就是那些具有独立功能的,被封装的代码块
return:仅仅表示结束当前函数,如果有返回值,则函数结束前 返回值:指的就是这一具有独立功能的代码块的计算结果传递给外界
配合return使用 返回值类型:就是返回值的数据类型(可兼容即可)
如果函数没有返回值,所以return可以忽略不写,return仅表示结束当期那函数而已。如果函数有返回值,return必须写。return 返回值;
主函数的格式分析
String[] args可以在执行程序的时候,可以给主函数传递一些参数
因为main函数没有返回值,所以return可以忽略不写。
不要函数的内部定义函数,函数必须在类里面,函数之间是平级关系。
在C/C++/python中函数的定义必须在调用之前
在Java当中都可以
2.函数的分类
有返回值有参数 有返回值无参数 无返回值有参数 无返回值无参数
有返回值的函数,参与运算 输出 赋值
无返回值的函数,仅调用
3.函数传参
-
实际参数-实参
在调用函数的时候给函数传递的数据叫实参(常量 变量)
-
形式参数-形参
定义函数的时候,参数列表中定义的变量。
-
实参是将什么东西传递给了形参
目前为止传的是常量在常量池中的地址
传递对象在堆内存中的地址去 -
局部变量
在函数中创建的变量称之为局部变量,局部变量的作用域仅仅在当前的函数当中。
形式参数一定是局部变量。 -
实参传递给形参的过程
4.函数栈
函数栈 函数的运行是基于栈内存运行的 栈是一个先进后出的结构
函数帧:位于栈顶的函数优先运行的 主函数一定是位于栈底
栈是一个先进后出的一个容器结构,例如子弹按顺序123456进栈,按顺序出栈654321。
可以将每一个函数理解为是子弹(函数帧/栈帧),位于栈顶的函数帧优先运行的
主函数绝对是第一个进栈的。return结束当前函数 -> 当前函数弹栈。
- 函数的设计流程是自上而下的设计
import java.util.Scanner;
class Demo04_02{
public static void main(String[] args){
//1.提示用户输入一个数字
Scanner scanner=new Scanner(System.in);
System.out.print("请输入一个数字:");
int num=scanner.nextInt();
//2.判断该数字是否是一个回文
if(isPalindrome(num)){ // pause1
System.out.println("是回文");
}else{
System.out.println("不是回文");
}
//return ;
}
public static boolean isPalindrome(int num){
//1.先计算该数字的反序
//2.对比反序的数字和数字本身
//pasue 2
return reverse(num)==num;
}
public static int reverse(int num){
int sum=0;
while(true){
sum=sum*10+num%10;
num/=10;
if(num==0){
return sum;
}
}
}
}
如果主函数的代码过多,那么主函数在进栈的时候会占用大部分的内存,而且可读性差(逻辑不清晰)维护成本高(牵一发而动全身)
5.函数重载
函数重载是同一个类中出现的同名函数。与权限,与返回值类型没关系,与形参名没关系。只和形参列表即参数列表的排列组合有关系(注意参数类型的向下兼容的关系)
重载的好处在于可以扩展函数的功能(函数重名但是参数类型不一样,执行的内容也可以不一样)
寻找适当函数的流程:
- 看是否有确切的参数定义 int+int 查看是否有(int,int)
- 看是否有可兼容的参数定义 int+int 查看是否有(double,double)
- 如果可兼容的参数定义有多个int+int,(double,int)或(int,double) 此时报错 引用不明确
6.函数的递归调用
递归的体现:函数自身调用函数自身
递归主要解决的问题:一般但凡能够被迭代解决的问题,递归都能解决,但是递归解决的问题,迭代就不一定能。
递归其实是分治法的一种实现方式(一种实现思路)
分治法是一种算法思想,没有具体的处理办法。分治法主要解决的问题是将大的问题进行拆分,拆分成若干个小的问题进行求解,最终将每个小问题的解进行合并。其实,分治法就是一种暴力枚举法,也是一种搜索最优答案的算法。
递归:先递,后归。
前进段:指的就是将问题从大到小。
结束段:问题无法再继续化小,则处理当前的问题。
返回段:将小问题处理完毕后向上返回。(有些问题是不需要返回的)
写递归时一定要先写 结束段
- 使用递归求连续数字和
class Test02{
public static void main(String[] args){
/*
计算1+2+3+4+5+...+98+99+100
f(n) 是求1~n的累加
f(100)就是我们当前最大的问题
写递归时,一定要先写它的end!
↓ 递
f(n)=f(n-1)+n
f(100)=f(99)+100 return 1+2+3+..+99 +100
f(99)=f(98)+99 return 1+2+...+98 +99
...
f(4)=f(3)+4 return 1+2+3+4
f(3)=f(2)+3 return 1+2+3
f(2)=f(1)+2 return 1+2
f(1)=1 return 1
→ end ↑ 归
*/
System.out.println(f(10));
}
public static int f(int n){
if(n==1){
return 1;
}
return f(n-1)+n;
}
}
有关汉诺塔
汉诺塔就是采用分治法,通过递归思想来得到答案。
四层汉诺塔
一、将前三个圆盘从X移动到Y,将第四个圆盘从X移动到Z,再将前三个圆盘从Y移动到Z
这样就分出了两个小问题:
- 怎样把前三个圆盘从X移动到Y
- 怎么将前三个圆盘从Y移动到Z。
二、将前三个圆盘从X移动到Y,也可以分解为:
将前两个圆盘从X移动到Z,将第三个圆盘从X移动到Y,再将前两个圆盘从Z移动到Y。
这样就又分出了两个更小的问题:
- 怎样把前两个圆盘从X移动到Z
- 怎样把前两个圆盘从Z移动到Y
三、将前两个圆盘从X移动到Z可以分解为:
将第一个圆盘从X移动到Y,将第二个圆盘从X移动到Z,再将第一个圆盘从Y移动到Z。
就这样将移动四个圆盘分解为移动三个圆盘的问题,将移动三个圆盘分解为移动两个圆盘的问题,最后分解为移动一个圆盘的问题。
四、那么如果有n个圆盘,也可以分解为移动前(n-1)个圆盘到中间柱,第n个圆盘移动到终点柱,再将(n-1)个圆盘从中间柱移动到终点柱的问题。
移动四个圆盘的整体过程如下:
class Hanno{
public static void main(String[] args){
//盘子的个数 出发 中间 目的
hanno(4,"X","Y","Z");
}
public static void hanno(int n,String begin,String mid,String end){
if(n==1){
System.out.println(begin+" -> "+end);
}else{
hanno(n-1,begin,end,mid);
System.out.println(begin+" -> "+end);
hanno(n-1,mid,begin,end);
}
}
}
7.常用函数
Math类
- Math.E
自然常数的double值 - Math.PI
π的double值 - Msth.abs(a)
返回 a 值的绝对值。 - Math.ceil(a)
返回最小的(最接近负无穷大)double 值,该值大于等于参数,并等于某个整数。 - Math.floor(a)
返回最大的(最接近正无穷大)double 值,该值小于等于参数,并等于某个整数。 - Math.hypot(x,y)
返回 s q r t ( x 2 + y 2 ) sqrt(x^2 +y^2) sqrt(x2+y2),没有中间溢出或下溢。 - Math.max(a,b)
返回两个值中较大的一个。 - Math.min(a,b)
返回两个值中较小的一个。 - Math.pow(a,b)
返回第一个参数的第二个参数次幂的值。 - Math.sqrt(a)
返回正确舍入的 double 值的正平方根。 - Math.random()
返回带正号的 double 值,该值大于等于 0.0 且小于 1.0。 - Math.rint(a)
返回最接近参数并等于某一整数的 double 值。 - Math.round(a)
返回最接近参数的整型。
String类
不是基本数据类型而是一个类,既然是类那么肯定有其相关的函数
查询相关
- char charAt(index)
返回指定索引处的 char 值。 - int indexOf(int ch)
返回指定字符在此字符串中第一次出现处的索引。 - int lastIndexOf(int ch)
返回指定字符在此字符串中最后一次出现处的索引。 - int length()
返回此字符串的长度。 - substring(int beginIndex, int endIndex)
返回一个新字符串,它是此字符串的一个子字符串。
判断相关
- boolean contains(String s)
当且仅当此字符串包含指定的 char 值序列时,返回 true。 - boolean endsWith(String s)
测试此字符串是否以指定的后缀结束。 - boolean startsWith(String prefix)
测试此字符串是否以指定的前缀开始。 - int compareTo(String anotherString)
按字典顺序比较两个字符串。 - boolean equals(String anotherString)
将此字符串与指定的对象比较。 - boolean equalsIgnoreCase(String anotherString)
将此 String 与另一个 String 比较,不考虑大小写。 - boolean isEmpty()
当且仅当 length() 为 0 时返回 true。
修改相关
注意!!!对字符串的修改永远都不是对其自身进行的修改
字符串本身是不可变的!!!
对字符串的修改往往都是新建个字符串将修改后内容赋值并返回新的字符串
- String replace(char oldChar, char newChar)
返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。 - String toUpperCase()
- 使用默认语言环境的规则将此 String 中的所有字符都转换为大写。
- String toLowerCase()
使用默认语言环境的规则将此 String 中的所有字符都转换为小写。 - String trim()
返回字符串的副本,忽略前导空白和尾部空白。