一、函数的定义
函数是定义在类中的一段独立的代码块,用来解决那些重复的且具有独立功能的。将这些具有独立功能的代码可以进行再次封装,封装出来的东西就成为函数,Java中,函数又被称为方法。
函数的主要作用是为了提高代码的复用性。而且降低了主函数的代码量,将主函数很是当的拆分,以便内存优化。
函数都是在栈内存中运行;运行的函数处在栈顶。
切记:千万不要在函数内部创建函数 函数必须在类里面 函数们之间是平级关系
在C/C++/Python当中 函数的定义必须在函数调用之前
在JAVA当中之前、之后都可以。
1函数格式:
访问权限 函数类型 返回值类型 函数名(参数列表){
函数体
return 返回值 ;
//如果是无返回类型,则return可省略不写,但其实还在。
//返回值的类型必须与返回值类型一致
}
访问权限:指的就是函数的使用范围(内部和外部)public protected 默认不写 private
函数类型:指的就是函数类型的分类,说的就是函数具体的使用场景 static(静态函数)、默认不写(成员函数)、abstract(抽象函数)、native(本地函数)、synchronized(同步函数)
函数名:就是程序员给这段代码自定义的名称(标识符)
参数列表:参数列表有若干个 参数类型 参数名.......组成 主要用于接收外界传递给函数的一些数据
函数体:就是那些具有独立功能代码段
返回值:指的就是这一具有独立功能的代码段的计算结果,需要传递给外界 配合return(这个值会返回给函数的调用者)
返回值类型:就是返回值的数据类型(可兼容)
class Test01{
public static void main(String[] args){
int a=10;
if(a>5){
//return; //return如果写在这则在此处结束当前函数
}
System.out.println("来了老弟~");
//这里return 省略了。
/*
主函数的格式分析
public 主函数是公开权限 最大权限
static 主函数是静态函数
void 该函数没有返回值
main 主函数的名称
String[] String[] 表示的是一个字符串数组(数据类型)
args 就是这个数据类型的变量名称
番外:我们可以在执行程序的时候 给主函数传递一些参数
return:发现return不在
!!!而是因为函数没有返回值 所以return可以忽略不写 不代表不存在
!!!return本身表示结束当前函数!
!!!如果函数有返回值 return 返回值; 必须写
*/
}
}
如果前面那个return没有被注释掉运行结果则会为空(null),因为函数被结束了而且没有要输出啥。
二、函数的分类
1.有返回值有参数
2.有返回值无参数
3.无返回值有参数
4.无返回值无参数
注意:有返回值的函数,参与运算、输出、赋值;
无返回值的函数,仅仅调用;举例:
// 以下都是错误的对无返回值函数的操作
// System.out.println(show());
// int d=show();
// int e=show()+10;
三、函数传参
实际参数----实参(调用函数时给函数传递的数据常量/变量叫做实参)
形式参数----形参(定义函数的时候,参数列表当中的数据叫做形参)
那么请问实参到底将什么传递给了形参?
..................
int a =4;
int b=4;
double c=pow(a,b);
................
public static double pow(int a,int b){
...........
return sum;
}
目前为止传的的是常量在常量池中的地址(以后学到 面向对象 时可能会遇到 传的是对象在堆内存中的地址)
注意: 但凡在函数中创建的变量称之为局部变量 局部变量的作用域仅仅在函数中
四、函数栈
栈是一个先进后出的容器(数据结构中讲过) 函数的内存是基于栈内存的。
举个栗子:
一个子弹按顺序123456进栈,按顺序出栈654321;
可以将一个函数理解为是子弹(函数帧/栈帧)位于栈顶的函数帧优先运行 主函数绝对是第一个进栈的
return 结束当前函数->当前函数弹栈
如何更好地理解函数栈呢?
首先按正常语句自上而下执行,遇到调用函数的语句就转到此函数的代码块,进行传参、运算,若函数有返回值,则返回给主函数中的调用语句,然后这条语句就相当于一个值,可以对它直接打印,也可以进行复制,之后继续执行主函数,直到遇到主函数的return语句,编译完成。这就相当于上述栗子中的123456进栈是一样的,然后出栈时谁先遇到return谁先弹栈。
五、函数重载
函数的重载指的就是同一个类中出现的同名函数。
与权限没关系,与返回值类型没关系,与参数名没关系
只有和参数类型的排列组合有关系(注意一下参数类型的向下兼容问题)
重载的好处就在于我们可以扩展函数的功能(函数重名,但是参数类型不一样,执行内容也可以不一样)
寻找适当函数的流程
1.看是否有确切的参数定义 int+int 查看是否有(int,int)
2.看是否有可兼容的参数定义 int+int 查看是否有(double,double)
3.如果可兼容的参数定义有多个int+int,(double,int)或(int,double) 此时报错 引用不明确
class Test01{
public static void main(String[] args){
int a=3;
int b=4;
System.out.println(add(a,b));
double d=3.14;
double e=5.44;
System.out.println(add(d,e));
System.out.println(add(3,3.14));
System.out.println(add(3.13,9));
}
//对两个小数进行加法运算
// public static double add(double c,double d){
// return c+d;
// }
public static String add(String a,String b){
System.out.println("String+String");
return a+b;
}
// public static double add(int a,double b){
// System.out.println("int+double");
// return a+b;
// }
// public static double add(double a,int b){
// System.out.println("double+int");
// return a+b;
// }
public static double add(double a,double b){
System.out.println("double+double");
return a+b;
}
//对两个整数进行加法运算
// public static int add(int a,int b){
// System.out.println("int+int");
// return a+b;
// }
}
六、函数的递归调用
递归的体现就是函数自身调用函数自身。
递归:先递,后归
前进段---------------------指的就是讲问题从大化小
结束段---------------------问题无法再继续化小,则处理当前的问题
返回段---------------------将小问题处理完毕之后,向上返回(有些问题是不需要返回的)
递归例题代码:
class Test02{
public static void main(String[] args){
/*
问题1:计算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;
}
}
递归主要解决什么问题呢?
一般而言,但凡能够被迭代(循环)解决的问题,递归都可以。
递归解决的问题,迭代就不一定了
递归其实是分治法的一种实现方式(一种实现思路)
递归就是函数在进栈,进栈的次数多了,势必会占内存,无法避免的
在某些问题上,递归所写的代码要比迭代写的代码少
在某些问题上,迭代是写不出来的,所以只能用递归
分治法是一种算法思想,分治法主要解决的问题是将大问题,进行拆分,拆分成若干个小的问题进行求解,最终将每个小问题的解进行合并。注意一定要写拆分的结束条件。
其实,分治法就是一种暴力破解法(穷举),也是一种搜索最优答案的算法。
下面说一个说一个既可用迭代解决也可用递归解决的斐波那切数列
class Test03{
public static void main(String[] args){
/*
问题2:斐波那契数列 求前20项
1 1 2 3 5 8 13 21 34 55 ......
f(n)指的是斐波那契的第n项
f(n)=f(n-1)+f(n-2) f(1)=1 f(2)=1
f(5)
f(4) f(3)
f(3) f(2) f(2) f(1)
f(2) f(1)
*/
//递归缺点: 越往后 越慢 代码比较简洁
//O(n*2^n)
for(int i=1;i<=20;i++){//O(n)
System.out.println(fibo(i));//O(2^n)
}
}
public static int fibo(int n){
if(n==1||n==2){
return 1;
}
return fibo(n-1)+fibo(n-2);
}
}
class Test04{
public static void main(String[] args){
fiboIterator(20);//用迭代的思想求前20项
}
//O(n)线性级别
public static void fiboIterator(int n){
int a=1;
int b=1;
System.out.println(a);
System.out.println(b);
int count=2;
int c;
while(true){
c=a+b;
System.out.println(c);
count++;
if(count==n){
return;
}
a=b;
b=c;
}
}
}
七、常用函数
Math类:
Math.E、Math.PI、Math.abs(a)、Math.ceil(a)、Math.floor(a)、Math.hypot(x,y)、Math.max(a,b)、Math.min(a,b)、Math.pow(a,b)、Math.sqrt(a)、Math.random()、Math.rint(a)、Math.round(a)
class Test01{
public static void main(String[] args){
System.out.println(Math.E);
System.out.println(Math.PI);
//大于指定数字的最小整数
System.out.println(Math.ceil(-2.1));
//小于指定数字的最大整数
System.out.println(Math.floor(2.3));
//求两点之间的距离 x=deltX y=deltY
System.out.println(Math.hypot(3,4));
//四舍五入为double值
System.out.println(Math.rint(3.5));
//四舍五入为int值
System.out.println(Math.round(3.5));
}
}
String类:
String不是基本数据类型而是一个类,既然是类那么肯定有其相关的函数
查询相关:char charAt(int index)、int indexOf(int ch) 、int lastIndexOf(int ch) 、int length()、substring(int beginIndex, int endIndex)
判断相关:boolean contains(String s)、boolean endsWith(String s)、boolean startsWith(String prefix) 、int compareTo(String anotherString)、boolean equals(String anotherString)、boolean equalsIgnoreCase(String anotherString) 、boolean isEmpty()
修改相关:
注意!!!对字符串的修改永远都不是对其自身进行的修改
字符串本身是不可变的!!!
对字符串的修改往往都是新建个字符串将修改后内容赋值并返回新的字符串
String replace(char oldChar, char newChar) 、String toUpperCase() 、String toLowerCase() 、String trim()
class Test02{
public static void main(String[] args){
String s="abcd";
/*
"abcd"
0123
*/
int a=321;
String s1="哈哈";
System.out.println(s1.length());
// System.out.println(a.length());
//获取指定角标处的字符
System.out.println(s.charAt(0));
//判断指定子串是否包含在s中
System.out.println(s.contains("ab"));
//判断指定子串是否在s的结尾
System.out.println(s.endsWith("cd"));
//按照字典顺序比较两个字符串的大小
//返回值有负数 0 正数
//负数 前者在后者ASCII之前
//0 前者和后者相等
//正数 前者在后者ASCII之后
System.out.println("abc".compareTo("abd"));
/*
abc
abd c-d=-1
*/
System.out.println("abc".compareTo("abc"));
//比较两个字符串是否相等(比的是内容)
System.out.println("abc".equals("abc"));
//IgnoreCase忽略大小写
System.out.println("ABC".equalsIgnoreCase("abc"));
//在字符串中从左到右查找指定元素第一次出现的位置
System.out.println("abcccccd".indexOf('c'));
System.out.println("abcccccd".indexOf("cd"));
System.out.println("".isEmpty());
s="abababab";
System.out.println(s.replace('a','c'));
System.out.println(s.substring(0,3));//[0,3)
System.out.println(s.toUpperCase());
System.out.println(" abc abc abc ".trim());
}
}
八、例题整理
class Test03{
public static void main(String[] args){
/*
问题1:求s2在s1中出现的次数
s1="abcabcbcacbabbabcba"
s2="abc"
推荐算法:KMP算法
*/
question1();
/*
问题2:判断字符串s是否是回文
s="上海自来水来自海上"
*/
question2();
/*
问题3:模拟trim的功能,自定义实现
s=" 安利给~ "
*/
question3();
/*
问题4:求s1和s2中最大的相同子串(s1.length()>s2.length())
s1="Python is a program language but is slow";
s2="Java is a program language but is fast"
*/
question4();
}
public static void question4(){
/*
问题4:求s1和s2中最大的相同子串(s1.length()>s2.length())
s1="Python is a program language but is slow";
s2="Java is a program language but is fast"
" is a program language but is "
*/
String s1="Python is a program language but is slow";
String s2="Java is a program language but is fast";
boolean flag=true;
for(int len=s2.length();len>=1;len--){
for(int i=0,j=len-1;j<s2.length();i++,j++){
String sub=s2.substring(i,j+1);
// System.out.println(sub);
if(s1.contains(sub)){
flag=false;
System.out.println("结果就是["+sub+"]");
break;
}
}
if(!flag){
break;
}
}
}
public static void question3(){
/*
问题3:模拟trim的功能,自定义实现
s=" 安利给~ "
*/
String s=" 123123123 ";
int left=0;
int right=s.length()-1;
while(s.charAt(left)==' '){
left++;
}
while(s.charAt(right)==' '){
right--;
}
String res=s.substring(left,right+1);
System.out.println("["+res+"]");
}
public static void question1(){
/*
问题1:求s2在s1中出现的次数
s1="abcabcbcacbabbabcba"
s2="abc"
*/
String s1="12376128736123123612312312536123123";
String s2="12";
int count=0;
for(int i=0;i<s1.length()-s2.length()+1;i++){
String sub=s1.substring(i,i+s2.length());
if(sub.equals(s2)){
count++;
}
}
System.out.println("s2在s1中出现了"+count+"次");
}
public static void question2(){
/*
问题2:判断字符串s是否是回文
s="上海自来水来自海上"
*/
String s="13088888031";
int left=0;
int right=s.length()-1;
boolean flag=true;
while(true){
if(s.charAt(left)==s.charAt(right)){
left++;
right--;
if(left>=right){
break;
}
}else{
flag=false;
break;
}
}
System.out.println("s是回文吗:"+flag);
}
}
import java.util.Scanner;
class Demo04_01{
public static void main(String[] args){
//1.先输入一个数字
Scanner scanner=new Scanner(System.in);
System.out.print("请输入一个数字:");
long num=scanner.nextLong();
//2.调用函数将num拆分求和
int sum=sumDigits(num);
System.out.println(sum);
}
public static int sumDigits(long n){
int sum=0;
while(true){
sum+=n%10;
n/=10;
if(n==0){
return sum;
}
}
}
}
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;
}
}
}
}
class Demo04_06{
public static void main(String[] args){
int count=0; //表示回文素数的个数
int num=2; //表示可能的回文素数的数字 从2开始~?
while(true){
//如果num是 回文素数
if(isHuiWenAndSuShu(num)){
count++;
System.out.print(num+" ");
if(count%10==0){
System.out.println();
}
}
if(count==100){
break;
}
num++;
}
}
public static boolean isHuiWenAndSuShu(int num){
return isHuiWen(num)&&isSuShu(num);
}
public static boolean isHuiWen(int num){
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;
}
}
}
public static boolean isSuShu(int num){
for(int i=2;i<=num/2;i++){
if(num%i==0){
return false;
}
}
return true;
}
}