一、概述
1.1 以前的方法:主方法
主方法是一种特殊的方法,是程序执行的入口。
class HelloImoc{
public static void main(String[] args){
System.out.pringln("Hello,imooc!");
}
}
1.2 以前的方法:从键盘输入数据的方法
Scanner sc=new Scanner(System.in);
sc.nextInt(); // nextInt()是从键盘获取整型数据的方法
sc.next(); // next()是从键盘获取字符串数据的方法
在方法部分,只介绍使用对象名来调用方法。后续学习面向对象时,对于静态方法其实是使用类名来调用的。
1.3 以前的方法:输出打印的方法
System.out.println(); // println():输出打印的方法
1.4 定义
由上可知,方法,就是用来解决一类问题的代码有序组合,是一个功能模块。
由于上述的三个方法,代表的是JDK提供的系统定义的方法,可以直接拿来使用。但是,此类方法并不能满足所有日常开发需求,因此,应该自定义方法。
二、方法的声明和调用
2.1 方法声明的语法格式和分类
1.以主方法为例:
(1)访问修饰符:
方法允许被访问的权限范围。有几种:
- public
- protected
- private
- 什么都不写
(2)返回类型:
可以是void以及任何的数据类型。
(3)方法名:
跟变量名命名规则一样。
(3)参数列表:
可以省略无参,即小括号里面可以为空。
参数列表是由参数类型、参数名组成。like变量的定义
2.方法的调用
Demo d=new Demo();
d.show(); // 通过对象名.函数名()来调用
以上的调用仅限主方法中,同类下的其他方法调用,只需要函数名()即可,不需要对象。
3.方法的分类、使用场景
根据方法是否带参数、是否有返回值,可以分为以下四类:
- 无参、无返回值的方法
- 无参、有返回值的方法
- 带参、无返回值的方法
- 带参、有返回值的方法
无参的使用场景:方法操作固定,没有变化。比如:
- 输出一串星号
- 后面面向对象中,输出成员变量的方法,因为成员变量在类中已经定义好了
除此之外,就需要使用参数。
4.方法的作用
减少代码量.比如:
- 以前的冒泡排序写法如下:
int[] a= {34,53,12,32,56,17};
int temp;
for(int i=0;i<a.length;i++) {
for(int j=0;j<a.length-1-i;j++) {
if(a[j]>a[j+1]) {
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
上述只是一个数组a,如果还有数组b、数组c等100个数组呢,上面13行的业务逻辑你要写100次吗?
单独写到一个方法中,用方法调用:
public void sort(){ // 新定义一个方法
int temp;
for(int i=0;i<a.length;i++) {
for(int j=0;j<a.length-1-i;j++) {
if(a[j]>a[j+1]) {
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
}
SortDemo ad=new SortDemo();
int[] a= {34,53,12,32,56,17};
int[] b= {85,73,25,56,34,48};
ad.sort(a); // 对数组a进行排序
ad.sort(b); // 对方法进行调用
2.2 无参、无返回值的方法
例题:一行打印输出一串星号?
方法定义的形式:
public void printStar() {}
业务代码如下:
package com.imooc.method;
public class MethodDemo {
// 新的打印输出星号的方法
public void printStar() { // 方法的定义,是在类MethodDemo的内部 // 无参,且void表示无返回值
System.out.println("***************************");
}
// 主方法,习惯放最后
public static void main(String[] args) {
MethodDemo myMethodDemo=new MethodDemo(); // 创建一个类MethodDemo的对象myMethodDemo
myMethodDemo.printStar(); // 使用对象名.方法名()去调用方法
System.out.println("欢迎来到java的世界!");
myMethodDemo.printStar();
}
}
--->
***************************
欢迎来到java的世界!
***************************
2.3 无参、有返回值的方法
之前的方法:Scanner类下的next()方法,返回值是String类型,就是无参、有返回值的方法。
Scanner sc=new Scanner();
sc.next(); // 该方法返回值是String类型
sc.nextInt(); // 该方法有返回值,是int类型
例题:求长方形的面积?
定义的形式:
public int area(){} // 有返回值,且是整型int。根据需求可以变为double类型等
业务代码如下:
package com.imooc.method;
public class Rectangle {
public int area() { // 无参
int length=10;
int width=5;
int getArea=length*width;
return getArea; // 有返回语句
}
public static void main(String[] args) {
Rectangle rc=new Rectangle();
System.out.println("长方形的面积为:"+rc.area());
}
}
--->
长方形的面积为:50
2.4 有参、无返回值的方法
例题:定义一个方法,求两个float类型数据的最大值,并在方法中打印输出?
定义的形式:
public void max(float a,float b){}
业务代码如下:
package com.imooc.method;
public class MaxDemo {
// 求最大值的方法
public void max(float a,float b) { // 有参 // void表示无返回值
float max;
if(a>b) {
max=a;
}else {
max=b;
}
System.out.println("两个数"+a+"和"+b+"的最大值为:"+max);
}
public static void main(String[] args) {
MaxDemo maxDemo=new MaxDemo();
int a=5,b=3; // 因为int可自动转换为float
maxDemo.max(a, b);
float m=5.6f,n=8.9f; // 调用时,定义变量 // 这里不一定非得是a、b,上面只是个形式参数
maxDemo.max(m, n);
maxDemo.max(9.8f, 12.8f); // 调用时,也可不定义变量,直接传字面值
}
}
--->
两个数5.0和3.0的最大值为:5.0
两个数5.6和8.9的最大值为:8.9
两个数9.8和12.8的最大值为:12.8
2.5 有参、有返回值的方法
例题:定义一个方法,求n!,然后再求1!+2!+3!+4!+5!?
以前使用的双重循环求阶乘。
定义的形式:
public int fac(int n){}
业务代码如下:
package com.imooc.method;
public class FacDemo {
public int fac(int n) { // 有参数
int s=1;
for(int i=1;i<=n;i++) {
s=s*i;
}
return s; // 有返回值 // 目的是为了下一步的运算
}
public static void main(String[] args) {
FacDemo facDemo=new FacDemo();
int fac=facDemo.fac(3);
System.out.println("3!="+fac); // 检验下求阶乘的方法是否生效
// 求1!+2!+3!+4!+5!
int sum=0;
for(int i=1;i<=5;i++) {
fac=facDemo.fac(i);
sum=sum+fac;
}
System.out.println("1!+2!+3!+4!+5!="+sum);
}
}
--->
3!=6
1!+2!+3!+4!+5!=153
方法不能定义在方法内,即不能嵌套定义。
2.6 练习题的教训:
错误演示;
public class DisCountDemo {
//根据商品总价输出折后总价
public void discount(float price){ // 有参 // void:无返回值
float dscPrice;
if(price<100){
dscPrice=price;
}
else if(price>=100&price<=199){
dscPrice=price*0.95;
}
else{
dscPrice=price*0.85;
}
System.out.println("折后商品的总价为:"+dscPrice);
}
public static void main(String[] args) {
DisCountDemo myDisCount=new DisCountDemo(); // 定义对象
float price=150; // 定义商品总价,存放到变量中
myDisCount.discount(price); //调用方法,输出折后商品总价
}
}
---> // 因为0.85在默认情况下,是double类型,转float类型会精度丢失
DisCountDemo.java:9: error: incompatible types: possible lossy conversion from double to float
dscPrice=price*0.95;
^
DisCountDemo.java:12: error: incompatible types: possible lossy conversion from double to float
dscPrice=price*0.85;
^
2 errors
改为:
将上述的float类型,全部换为double.
public class DisCountDemo {
//根据商品总价输出折后总价
public void discount(double price){ // 有参,无返回值
double dscPrice;
if(price<100){
dscPrice=price;
}
else if(price>=100&price<=199){
dscPrice=price*0.95;
}
else{
dscPrice=price*0.85;
}
System.out.println("折后商品的总价为:"+dscPrice);
}
public static void main(String[] args) {
DisCountDemo myDisCount=new DisCountDemo(); // 定义对象
double price=150; // 定义商品总价,存放到变量中
myDisCount.discount(price); //调用方法,输出折后商品总价
}
}
--->
折后商品的总价为:142.5
三、数组作为方法参数
3.1 例题1:输出数组元素
定义一个方法,打印输出数组元素的值?
定义的形式:
public void printArray(int[] arr){}
业务代码如下:
package com.imooc.method;
public class ArrayMethod {
public void printArray(int[] arr) { // 数组作为方法参数
for(int i=0;i<arr.length;i++) {
System.out.print(arr[i]+" ");
}
System.out.println();
}
public static void main(String[] args) {
int[] arr= {10,20,30,40,50};
ArrayMethod am=new ArrayMethod();
am.printArray(arr);
}
}
--->
10 20 30 40 50
2.习题:
3.2 例题2:查找数组元素
定义一个方法,查找数组元素的值?
定义的形式:
- 方法的参数:数组、要查找的元素
- 方法的返回值:boolean类型
public Boolean search(int n,int[] arr){}
业务代码如下:
package com.imooc.method;
import java.util.Scanner;
public class ArraySearch {
public boolean seach(int n,int[] arr) { // 有参数
boolean flag=false; // 默认是flase,即没找到
for(int i=0;i<arr.length;i++) {
if(arr[i]==n) {
flag=true; // 表示找到了
break; // 如果找到了,就立马跳出本循环,不执行后续循环
}
}
return flag; // 有返回值
}
public static void main(String[] args) {
int[] arr1= {10,20,30,40,50,60};
System.out.println("请输入要查找的数据:");
Scanner sc=new Scanner(System.in);
int n1=sc.nextInt();
ArraySearch as=new ArraySearch();
boolean flag1=as.seach(n1, arr1);
if(flag1) {
System.out.println("找到了!");
}else {
System.out.println("没找到!");
}
}
}
--->
请输入要查找的数据:
30
找到了!
请输入要查找的数据:
32
没找到!
四、方法的重载
3.1 概念
1.方法重载:就是方法名相同,但是参数不同。
参数不同指的是参数的数据类型不同,也可以指参数数量不同。
以下三个方法是重载方法:
public void dispaly(){};
public void dispaly(){int n};
public void dispaly(){float n};
以下两个方法不是重载方法:因为参数的数量、参数的数据类型都相同。
public void dispaly(){int n};
public void dispaly(){int d}; // 只是参数名不同,没用
2.应用场景:
因为实现某一相同功能,针对不同的参数,如int、long,float、double等,针对多个方法只起一个方法名即可。
平时常用的println()
其实就是多个重载的方法,用于输出不同类型的数据。
3.2 案例应用
例题:定义三个方法,实现int、double和数组类型和?
package com.imooc.method;
public class MathDemo {
// 求两个int类型数的和
public int plus(int m,int n) { // 方法名叫plus
return m+n;
}
// 求两个double类型数的和
public double plus(double m,double n) { // 方法名叫plus
return m+n;
}
// 求数组元素的累加和
public int plus(int[] arr) { // 方法名叫plus
int sum=0;
for(int i=0;i<arr.length;i++) {
sum=sum+arr[i];
}
return sum;
}
public static void main(String[] args) {
int m=5,n=10;
int[] arr= {1,2,3,4,5,6};
MathDemo mathDemo=new MathDemo();
System.out.println("int类型的和:"+mathDemo.plus(m, n));
System.out.println("double类型的和:"+mathDemo.plus(5.6,7.8));
System.out.println("数组元素的和:"+mathDemo.plus(arr));
}
}
--->
int类型的和:15
double类型的和:13.399999999999999
数组元素的和:21
四、方法传值
4.1 基本数据类型的传值
例题1:
对两个变量的值进行交换,并打印输出?
package com.imooc.method;
public class ExchangeDemo {
// 交换方法
public void swap(int a,int b) {
int temp;
System.out.println("交换前:a="+a+",b="+b);
temp=a;a=b;b=temp;
System.out.println("交换后:a="+a+",b="+b);
}
public static void main(String[] args) {
int m=4,n=5;
ExchangeDemo ed=new ExchangeDemo();
System.out.println("交换前:m="+m+",n="+n);
ed.swap(m,n); // 这里的m,n只是传值进入了上述的swap子方法
System.out.println("交换后:m="+m+",n="+n);
}
}
--->
交换前:m=4,n=5
交换前:a=4,b=5
交换后:a=5,b=4
交换后:m=4,n=5 // 主方法中的m,n前后没有变化
真实的项目中,主方法的简化如下:
package com.imooc.method;
public class ExchangeDemo {
// 交换方法
public void swap(int a,int b) {
int temp;
System.out.println("交换前:a="+a+",b="+b);
temp=a;a=b;b=temp;
System.out.println("交换后:a="+a+",b="+b);
}
public void swapTest() { // 再定义一个新方法,在方法体中调用上述方法
int m=4,n=5;
System.out.println("交换前:m="+m+",n="+n);
swap(m,n); // 直接用方法名调用即可,不用像在主方法中调用一样,实例化对象、用对象调用了
System.out.println("交换后:m="+m+",n="+n);
}
public static void main(String[] args) {
ExchangeDemo ed=new ExchangeDemo();
ed.swapTest(); // 在主方法中调用,代码简洁
}
}
--->
交换前:m=4,n=5
交换前:a=4,b=5
交换后:a=5,b=4
交换后:m=4,n=5 // 跟上面的结果是一样的
例题2:
在主方法中调用了子方法,那么子方法影响主方法中变量的值吗?
package com.imooc.method;
public class ExchangeDemo2 {
public void add(int n) {
n++;
System.out.println("方法中n="+n);
}
public static void main(String[] args) {
int n=10;
System.out.println("方法调用前n的值:"+n);
ExchangeDemo2 ed=new ExchangeDemo2();
ed.add(n);
System.out.println("方法调用后n的值:"+n);
}
}
--->
方法调用前n的值:10
方法中n=11
方法调用后n的值:10 // 子方法调用,对主方法中的变量值没有影响
4.2 数组的传值
上面是基本数据类型的参数传值,接下来是数组作为方法参数的传值:
package com.imooc.method;
public class ArrayDemo {
// 定义一个方法,用于修改某个数组元素值
public void updateArray(int[] a){
a[3]=15;
System.out.println("数组a的元素为:");
for(int n:a) {
System.out.print(n+" ");
}
System.out.println();
}
public static void main(String[] args) {
ArrayDemo ad=new ArrayDemo();
int[] a1= {1,2,3,4,5};
System.out.println("方法调用前数组a1的元素为:");
for(int n:a1) {
System.out.print(n+" ");
}
System.out.println();
ad.updateArray(a1); // 方法调用
System.out.println("方法调用后数组a1的元素为:");
for(int n:a1) {
System.out.print(n+" ");
}
}
}
--->
方法调用前数组a1的元素为:
1 2 3 4 5
数组a的元素为:
1 2 3 15 5
方法调用后数组a1的元素为:
1 2 3 15 5 // 子方法调用,影响到了主方法中的数组元素
之所以是这样,是因为数组是引用数据类型,面向对象中的对象同理。
数组名a,指向了内存空间中数组的第一个元素a[0]。
上述不同,为何这样设计?
五、可变参数列表
5.1 概念
可变参数,是一种特别的参数:即参数的数量不确定、可以随时变化。或者叫可变原参数、可变参数类型。
形式:
public void sum(int... n) {}; // 视为有0~n个整型变量
5.2 案例应用
例题1:
定义一个方法,方法中的参数是可变参数列表形式?
package com.imooc.method;
public class Argsdemo {
// 求和
public void sum(int... n) {
int sum=0;
for(int i:n) { // 用增强型for循环,取出可变参数列表中的每一个参数 // like数组
sum=sum+i;
}
System.out.println("sum="+sum);
}
public static void main(String[] args) {
Argsdemo ad=new Argsdemo();
ad.sum();
ad.sum(1);
ad.sum(1,2);
ad.sum(1,2,3); // 不管是几个参数,方法sum()都hold的住
}
}
--->
sum=0
sum=1
sum=3
sum=6
例题2:
定义一个方法,在可变参数列表中进行查找?
package com.imooc.method;
public class ArgsDemo1 {
public void search(int n,int... a) { // 参数列表中,如果有两个以上的参数,可变参数一定是放最后的!
boolean flag=false;
for(int a1:a) {
if(a1==n) {
flag=true;
break;
}
}
if(flag) {
System.out.println("找到了!"+n);
}else {
System.out.println("没找到!"+n);
}
}
public static void main(String[] args) {
ArgsDemo1 ad1=new ArgsDemo1();
ad1.search(3, 1,2,3,4,5); // 1,2,3,4,5是传给可变参数的
int[] arr= {1,2,3,4,5};
ad1.search(3, arr); // 也可以将数组,传给可变参数列表
}
}
--->
找到了!3
找到了!3
3.注意:
(1)一个方法中,只能有一个可变参数列表;
(2)以下说明,可变参数的底层实现其实是数组。可变参数功能更强大一些
5.3 可变参数列表作为方法参数的重载问题
方法重载时,两个方法的调用顺序:可变参数列表所在的方法,是最后被调用访问的
package com.imooc.method;
public class ArgsDemo3 {
public int plus(int a,int b) {
System.out.println("不带可变参数的方法被调用!");
return a+b;
}
public int plus(int... a) {
int sum=0;
for(int n:a) {
sum=sum+n;
}
System.out.println("带可变参数的方法被调用!"); // 可变参数列表所在的方法,是最后被访问的
return sum;
}
public static void main(String[] args) {
ArgsDemo3 ad3=new ArgsDemo3();
System.out.println("和为:"+ad3.plus(1,2));
}
}
--->
不带可变参数的方法被调用!
和为:3
感觉可变参数列表就像是兜底的
5.4 文档注释:
1.以下是以前的多行注释:
package com.imooc.method;
public class ArgsDemo3 {
/* // 多行注释
public int plus(int a,int b) {
System.out.println("不带可变参数的方法被调用!");
return a+b;
}
*/
public int plus(int... a) {
int sum=0;
for(int n:a) {
sum=sum+n;
}
System.out.println("带可变参数的方法被调用!");
return sum;
}
public static void main(String[] args) {
ArgsDemo3 ad3=new ArgsDemo3();
System.out.println("和为:"+ad3.plus(1,2)); // 此时,只能调用可变参数了
}
}
--->
带可变参数的方法被调用!
和为:3
2.以下是文档注释:
因为可以通过Javadoc
命令,将代码中的注释提取出来,生成程序的帮助文档。
3.如何生成文档内容?
六、方法调试
跟其他的调试一模一样,唯一不同的是可以通过快捷键进入方法内部,查看方法内代码的执行细节。
演示如下:
Comments | NOTHING