为什么使用数组
如何存储100名学生的成绩?
办法:使用变量存储,重复声明100个double类型变量即可。
缺点:麻烦,重复操作过多。
如何让100名学生成绩全部加1?
办法:100个变量重复相同操作,直至全部完毕。
缺点:无法进行统一操作。
数组的概念
- 概念:一组连续的存储空间,存储多个相同数据类型的值。 特点:1.类型相同 2.长度固定
数组的创建
数组中的每个数据格被称为“数组元素”。
对每个元素进行赋值或取值的操作被称为“元素的访问”。
- 访问元素时,需要使用“下标”(从0开始)。
- 访问的语法:数组名[下标]; 例如 存:a[0]=10; 取:a[0];
数组的使用
public class TestCreateAraay{
public static void main(String[] args){
int [] a = new int[5];//创建数组
a[0] =5;//依次赋值
a[1] =3;
a[2] =4;
a[3] =1;
a[4] =2;
System.out.println(a[0]);//依次取值
System.out.println(a[1]);
System.out.println(a[2]);
System.out.println(a[3]);
System.out.println(a[4]);
for(int i = 0;i<5;i++)
System.out.println(a[i]);
}
}
下标的范围
有效范围:0~数组的长度-1 通过数组名+ .length可以访问数组的长度
数组的遍历
- 遍历:从头到尾,逐一对数组的每个元素进行访问。
for(int i = 0;i<a.length;i++)
System.out.println(a[i]);
数组的默认值
在没有为数组元素赋值的情况下,依旧可以正确的访问。
数组的默认值:
整数:0
小数:0.0
字符:\u0000
布尔:false
其它:null
数组创建语法
先声明、再分配空间:
数据类型[] 数组名; int[] array1 ;
数组名=new 数据类型[长度]; array1 = new int[8];
声明并分配空间:
数据类型[] 数组名 = new 数据类型[长度]; int[] array2 = new int[10];
声明并赋值(繁):
数据类型[] 数组名 = new 数据类型[] {value 1,value2,value3…};
int array2 = {1,2,3,4,5};
for(int i=0;i<array2.length;i++){
System.out.println(array2[i]);
}
给定一个数组,求平均值
public class TestAvg{
public static void main(String[] args){
int[] num = new int[]{1,3,4,5,6,10};
int sum = 0;
for(int i=0; i<num.length; i++){
sum+=num[i];
}
double avg = sum/num.length;
System.out.println("平均值为" +avg);
}
}
import java.util.Scanner;
public class TestSearch{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.println("请输入一个整数");
int n = input.nextInt();
int index = -1;//代表n从未出现在数组中
int[] numbers = new int[]{1,3,4,5,6};
//循环查找的过程
for(int i=0;i<numbers.length;i++){
if(n==numbers[i]){
index =i;//改变index,代表n所出现的下标
break;
}
}
System.out.println(index);
}
}
数组的排序
-
JDK排序:java.util.Araays.sort(数组名); //JDK提供(升序)
import java.util.Arrays; public class TestSort{ public static void main(String[] args){ int[] nums = new int[]{4,3,5,2,1}; //借助JDK提供的数组工具进行排序 Arrays.sort(nums); //第一次遍历(升序) for(int i=0;i<nums.length;i++){ System.out.println(nums[i]); } System.out.println(Arrays.toString(nums)); //降序:需要手工的方式完成元素的倒置1 2 3 4 5 for(int i=0;i<nums.length/2;i++){//两值交换,借助第三变量 int temp=nums[i]; nums[i]=nums[nums.length-1-i]; nums[nums.length-1-i]=temp; } for(int i=0;i<nums.length;i++){ System.out.println(nums[i]); } System.out.println(Arrays.toString(nums)); } }
方法的定义
概念:实现特定功能的一段代码,可反复使用。
定义语法:
public static void 方法名称(){
//方法的主体
}
- 经验:将需要在多个位置重复使用的一组代码,定义在方法内部。
定义的位置
- 方法定义在类的内部,与main方法并列。
//位置1
public class TestMethod{
//位置2
public static void main(String[] args){
//位置3
}
//位置4
}
//位置5
- 正确位置:位置2、位置4
public class TestMethod{
public static void main(String[] args){
System.out.print("床前明月光"+"\n"+"----------"+"\n");
System.out.print("疑是地上霜"+"\n"+"----------"+"\n");
System.out.print("举头望明月"+"\n"+"----------"+"\n");
System.out.print("低头思故乡"+"\n"+"----------"+"\n");
System.out.println("床前明月光");
pingSign();
System.out.println("疑是地上霜");
pingSign();
System.out.println("举头望明月");
pingSign();
System.out.println("低头思故乡");
pingSign();
}
//自定义方法(在一行中输入10个减号,代表分隔符)
public static void pingSign(){
for(int i=0;i<=10;i++){
System.out.print("-");
}
System.out.println();
}
}
注意:调用方法时,会优先执行方法内部代码,结束后,返回到方法调用出,继续向下执行。
方法的参数
多数情况下,方法与调用者之间需要数据的交互;调用者必须提供必要的数据,才能使方法完成相应的功能。
- 调用方法时,所传入的数据被称为“参数”。
形参与实参
-
定义语法:
public static void 方法名称(形式参数){ 经验:“形参” 等价于局部变量的“声明”
//方法主体
}
-
调用语法:
方法名称(实际参数); 经验:“实参”等价于局部变量的赋值
作用:方法的参数可以让代码功能更灵活、普适性更高,易于修改及维护。
单个参数:
public class TestMethod02{
public static void main(String[] args){
/*
实际参数:10
调用带参方法时,必须传入实际参数,为形式参数赋值。
*/
System.out.println("床前明月光");
pingSign(6);
System.out.println("疑是地上霜");
pingSign(6);
System.out.println("举头望明月");
pingSign(6);
System.out.println("低头思故乡");
pingSign(6);
}
//定义:打印count个分隔符的函数
public static void pingSign(int count){ /*形式参数:int count
当方法被执行时,循环count次。
*/
for(int i=1;i<=count;i++){
System.out.print("-");
}
System.out.println();
}
}
多个参数:
public class TestMethod03{
public static void main(String[] args){
//需求是:在多次调用pingSign方法时,可以打印不同次数的符号
//那么现在我们还需要在每次打印时可以打印不同的符号!
System.out.println("床前明月光");
pingSign(6,'-'); //实参:(6,-) 调用带参方法时,依次传入实参,
System.out.println("疑是地上霜"); //类型、个数、顺序、必须与形参对应。
pingSign(6,'#');
System.out.println("举头望明月");
pingSign(6,'*');
System.out.println("低头思故乡");
pingSign(6,'$');
}
public static void pingSign(int count,char sign){ /*
形参:int count,char sign
当方法被执行时,打印count次sign
*/
for(int i=1;i<=count;i++){
System.out.print(sign);
}
System.out.println();
}
}
如何定义参数
经验:根据具体的业务需求,来定义方法的参数。
用户名【 】 密码 【 】
public static boolean login(String usename,String password){
}
用户名【 】 密码 【 】 验证码 【 】
public static boolean login(String name,String pwd,String checkNo){
}
返回值与返回值类型
概念:方法执行后的返回结果。
方法执行后,一些情况下无需返回结果;另一些情况下则必须返回结果。
例如:存款操作无需返回结果;
取款操作必须返回结果。
定义语法: 规定返回值的具体类型(基本、引用、void)
public static 返回值类型 方法名称(形式参数列表){
//方法主体
return value; //返回值(根据需求返回一个结果(值)。
}
调用语法:
变量=方法名称();可以接收方法执行后返回的值 变量类型与返回值类型一致。
需求:定义方法,计算两个数的和,并返回结果,在main中打印。
public class TestReturn{
public static void main(String[] args){
int result =add(5,7);
System.out.println(result);
//在计算了5+7的总和之后,继续与20进行相加求和
int result2 = add(result,20);
System.out.println(result2);
}
public static int add(int num1,int num2){
int sum = num1+num2;
return sum;
}
}
public class TestReturn2{
public static void main(String[] args){
int result = add(5,6); 接收返回值:
System.out.println(result); 方法调用的表达式,最终即代表了所返回的结果。
} 返回值类型: 定义时,即约定了返回的结果类型。
public static int add(int a, int b){
return a+b; 返回值:与返回值类型匹配的具体结果。在return关键字的后面追加具体值。
}
}
public class TestResultValue{
public static void main(String[] args){
String result = isEven(10);
System.out.println(result);
}
public static String isEven(int num){
if(num % 2==0){
return "偶数"; //当有返回值的方法存在分支结构时,必须保证每一条分支都具有正确的返回值。
}else{
return "奇数";
}
}
}
return的两种用法
应用在具有返回值类型的方法中:
- return value; //表示结束当前方法,并伴有返回值,返回到方法调用处。
应用在没有返回值类型(void)的方法中:
- return; //表示结束当前方法,直接返回到方法调用处。
- break; 表示结束当前循环,并继续往下执行代码
public class Demo{
public static void main(String[] args){
show();
}
public static void show(){
for(int i=1;i<=10;i++){
System.out.println("当前值"+i);
if(i==5){
return;//结束当前方法,返回到方法调用处
}
}
System.out.println("......")//return直接结束了当前方法,所以不会再有输出
}
}
总结
-
注意:一个类中可以定义多个方法,方法之间属于并列关系,不可嵌套。
-
经验:一个方法只做一件事。(单一职能原则)
-
好处:
减少代码冗余
提高复用性
提高可读性
提高可维护性
方便分工合作。
## 多级调用
public class TestNestInvoke{
public static void main(String[] args){
m1();
}
public static void m1(){
System.out.println("你好");
m2(); //优先执行方法内部代码,结束后,返回到调用处,继续向下执行。
System.out.println("美女");
}
public static void m2(){
System.out.println("王者");
System.out.println("荣耀");
}
}
无穷递归
public class TestRecursionInvoke{
public static void main(String[] args){
m1(); //运行结果:嗨 嗨 嗨 嗨……
}
public static void m1(){
System.out.println("嗨");
m1();
System.out.println("哈喽");
}
}//Exception in thread "main" java.lang.StackOverflowError 栈内存溢出
当方法自己调用自己时,如果没有正确的出口条件,则产生无穷递归。
递归
-
什么是递归?
·解决具有既定规律的问题时,在方法内部再次调用自身方法的一种编程方式。
-
何时使用递归?
当需要解决的问题可以拆分成若干个小问题,大小问题的解决方式相同,方法中自己调用自己。
使用循环解决的常规问题,都可以替换为递归解决。
-
如何正确使用递归?
·设置有效的出口条件,可以让调用链上的每个方法都可以正确返回,避免无穷递归。
循环阶乘
- 计算5的阶乘:5!=5* 4 * 3 * 2 * 1;
public class TestFactorial{
public static void main(String[] args){
System.out.println(factorial(5));
}
public static int factorial(int n){
int sum = 1;
for(int i=2;i<=n;i++){
sum *=i;
}
return sum;
}
}
递归阶乘
阶乘的定义:n! = n * (n-1) * (n-2) * (n-3)……
【5!=120】 5! = 5 * 4! 递进:每一次推进,计算都比上一次变得简单,直至简单到无需
【4!=24】 4! = 4 * 3! 继续推进,就能获得结果。也叫到达出口。
【3!=6】 3! = 3 * 2!
【2!=2】 2! = 2 * 1!
1! = 1 【1的阶乘就是1】
回归:基于出口的结果,逐层向上回归,依次计算每一层的结果,直至回归到最顶层。
public class TestFactorial2{
public static void main(String[] args){
//计算阶乘
int result =getFive(5);
System.out.println(result);
}
//计算5的阶乘
public static int getFive(int n){//n=5
return n *getFour(n-1);
}
//计算4的阶乘
public static int getFour(int n){//n=4
return n *getThree(n-1);
}
//计算3的阶乘
public static int getThree(int n){//n=3
return n *getTwo(n-1);
}
//计算2的阶乘
public static int getTwo(int n){//n=2
return n *getOne(n-1);
}
//计算1的阶乘
public static int getOne(int n){//n=1
return n;
}//多个方法解决问题的思路相同,同时遵循着相同的规律。
}//如何整合成为一个方法?
public class TestFactorial2{
public static void main(String[] args){
//计算阶乘
int result =factoria(5);
System.out.println(result);
}
public static int factoria(int n){
if(n==1){ //增加出口条件,n=1时,无需计算阶乘,直接返回结果1.
return 1;
}
return n * factoria(n-1);
}
}
- 注意:所有能以递归解决的问题,循环都可以解决。当解决复杂问题时,递归的实现方式更为简单。