什么是Java方法?
Java方法,也就是函数,就是就是用来解决一类问题的代码的有序组合,是一个功能模块。
方法的声明
访问修饰符 返回类型 方法名(参数列表) {
方法体
}
public static void main(String[] args) {
System.out.println("Hello,World!");
}
访问修饰符
访问修饰符就是方法允许被访问的范围,如上述中的main方法,public就是访问修饰符,表示公共的,可以在Java程序的任意位置被访问。static表示静态的,表示谁可以使用该方法,类和类的对象都可以使用。
返回类型
返回类型可以是void和其他任何类型的数据(包括自己创造的数据类型)。void表示空,即该方法没有返回值。
如果一个方法存在返回值,则方法定义上的返回值类型就是该返回值的类型(可以是任意类型,包括自己创建的类型)
方法名
参数列表
参数列表可以省略,既没有参数,同样参数可以有多个,每个参数之间使用逗号间隔,参数由数据类型和参数名构造,类似变量的定义。
方法的分类
根据参数和返回值,方法可以分为四类:
- 无参无返回值;
- 无参有返回值;
- 带参无返回值;
- 带参有返回值;
无参无返回值的方法
如图所示,现有要求需要我们在多个场景来打印文字上下方的*符号串,对于这样一种重复的行为,我们希望将这条打印语句放置在一个方法里面,然后每次遇到同样的要求,只需要调用方法就可以了。
public class Practice {
// 打印输出星号的方法
public void printStar() {
System.out.println("********************************");
}
public static void mian (String[] args) {
//对于一个没有使用static修饰的方法,需要使用类的对象来调用
//创建一个Practice类的对象prc
Practice prc=new Practice();
//使用对象名.方法名()去调用方法
prc.printStar();
//如果是static修饰的方法,调用可以是类的调用方法或者直接调用,如Practice.printStar()或printStra()
System.out.println("欢迎来到Java的世界!");
prc.printStar();
}
}
在方法上的文档注释可以作为该方法的说明,当光标停滞在方法上时,会有弹窗说明。
文档注释一般放在方法上,构造器上和类上。表明这三者的作用
无参有返回值的方法
求一个长宽都是整数的长方形面积。
public class Rectangle {
/**
*一个求长方形面积的方法area()
*长宽都是整数,所以返回类型为int
*/
public int area() {
int length=10;
int width=5;
int area=length*width;
return area;//返回语句,变量名和方法名可以一致,同时注意方法返回值需要和规定的返回值一致。
}
public static void main(String[] args) {
Rectangle rc=new Rectangle();
int a = rc.area();//只要返回值不是void,可以在调用方法时,设置变量来承接该方法的返回值
System.out.println("长方形的面积为:"+rc.area());
}
}
带参无返回值的方法
定义一个求两个float类型的数据最大值的方法,在方法中将最大值打印输出。
public class MaxDemo {
public void max(float a, float b) {//形式参数(形参)
float max;
if(a > b) {
max = a;
} else {
max = b;
}
System.out.println("最大值为:" + max);
}
public static void main(String[] args) {
MaxDemo md = new MaxDemo();
//在Java中,当定义方法规定参数的参数类型和参数个数时,必须在调用该方法时完全满足
//传递数值时主方法中可以是变量,也可以是一个字面值,不同类型传递会出现类型转换
//float f1 = 1.2;
//float f2 = 2.2;
//md.max(f1,f2);
//在调用该方法时,对于基本数据类型,方法的参数类型一般不会兼容(是指高级变量转为低级变量不兼容)
md.max(1.1, 1.3);//实际参数(实参)
}
}
带参有返回值的方法
定义一个求n!的方法,然后再求1!+ 2!+3!+4!+5!
public class Four {
//方法不能嵌套定义
//求阶乘的方法
public int fac(int n) {
int s=1;
for(int i=1;i<=n;i++) {
s*=i;//s=s*i;
}
return s;
}
//阶乘和
public int facSum(int n){
int sum = 0;
for(int i=0;i<n;i++){
//可以在无static的方法中直接调用另一个无static修饰的方法
sum = sum + fac(i);
}
return sum;
}
public static void main(String[] args) {
Four four=new Four();
int fac=four.fac(3);
System.out.println("3!="+fac);
int sum=0;
//求1!+2!+3!+4!+5!
for(int i=1;i<=5;i++){
fac=four.fac(i);
sum+=fac;
}
System.out.println("1!+2!+3!+4!+5!="+sum);
}
}
方法的定义必须定义在类的里面,但是不能定义在另外一个方法的里面。方法不能嵌套,带有返回值的方法是为了参与进一步的运算。
数组作为方法参数
定义方法,打印输出数组元素的值。
public class Five {
//打印输出数组元素的值
public void printArry(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};
Five am=new Five();
am.printArry(arr);
//也可以是am.printArry(new int[]{10,20,30,40,50});
}
}
合并数组
public class Demo {
public int[] getArray(int[] a,int[] b){
int[] c = new int[a.length+b.length];
//将a数组元素填充到c数组中
for(int i = 0;i<a.length;i++) {
c[i] = a[i];
}
for(int i = 0;i<b.length;i++) {
int j = i + a.length;//填充a数组后,索引应该是a.length开始
c[j] = b[i];
}
return c;
}
public static void main(String[] args) {
Demo demo = new Demo();
int[] arr1 = {1,2,3};
int[] arr2 = {4,5,6};
demo.getArray(arr1,arr2);
}
}
方法重载
方法重载简单概括就是方法名相同,参数列表不同。
//如果方法名相同,参数列表也相同,这属于方法的重复定义,不属于方法重载
public void hello(){}
public int hello(){}
//参数列表和参数的个数,参数的类型,参数的排序有关,和参数名无关
public void hello(String str){}
public void hello(String s){}//这两个不属于方法重载
public void hello(int a,String str){}
public void hello(String str,int a){}//这两个属于方法重载
通过方法重载可以定义很多相似的方法,这些方法共用一个方法名,根据参数的不同决定调用哪个方法。
定义三个同名方法,实现int、double和数组类型的求和。
public class MathDemo {
//求两个int类型数的和
public int plus(int m,int n){
return m+n;
}
//求两个double类型数的和
public double plus(double m,double n){
return m+n;
}
//求数组元素的累加和
public int plus(int[] arr){
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));
}
}
方法的传值
基本数据类型的传值
对两个变量的值进行交换并打印输出(传值问题)
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(){
//ExchangeDemo ex=new ExchangeDemo();
//普通方法调用方法不需要定义对象,直接调用即可 方法名(实参);
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 ex=new ExchangeDemo();
ex.swapTest();
/*int m=4,n=5;
System.out.println("交换前:m="+m+","+"n="+n);
ex.swap(m,n);
System.out.println("交换后:m="+m+","+"n="+n);*/
}
}
在方法运行之后,我们会发现,m与n的值并没有发生改变。这是因为首先创建m,n变量,会在内存中开辟空间存储对应的值,然后在方法调用的时候把m和n的值传给变量a,b,这时候只是把4和5这两个值传过去了。并不是把m和n的内存地址传递过去了。
总结:如果方法的参数是基本数据类型,那么在方法内对参数进行修改,不会影响到传递的实际参数。
数组的传值(通过数组来看引用数据类型的传值)
public class Ten {
//定义一个用于修改某个数组元素值的方法
public void updateArry(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) {
Ten b=new Ten();
int[] a1= {1,2,3,4,5};
System.out.println("方法调用前数组a1元素为:");
for(int n:a1) {
System.out.print(n+" ");
}
System.out.println();
b.updateArry(a1);
System.out.println("方法调用后数组a1元素为:");
for(int n:a1) {
System.out.print(n+" ");
}
}
}
如果主方法中声明的是数组(引用数据类型),则传值是把变量地址传过去了(传过去的是数组的第一个元素的地址),在普通方法中修改变量会影响主方法的变量。传值都是传的的变量里的值,基本数据类型的是值本身,引用类型的是对象的地址。
总结:当方法的参数为引用数据类型时,在方法中对参数进行修改,会影响到方法外的参数。
特殊:String虽然时引用数据类型,但是它经过方法后不会被修改。
可变参数列表
可变参数列表指的是参数的数量不固定,但是参数的类型是固定的,参数列表规定了是哪一种类型,随后的参数就只能是哪一种类型。
public void sum(int...n) {
}
public class Demo {
//求和
public void sum(int...n) {
int sum = 0;
for(int i:n) {//其实我们可以将可变参数列表看作为一个数组
sum = sum + i;
}
System.out.println("sum="+sum);
}
public static void main(String[] args) {
Demo de = new Demo();
de.sum(1);
de.sum(1,2);
de.sum(1,2,3);
//de.sum(1,1.2);传入的必须是int类型
//de.sum(new int[]{1,2,3});也可以用数组代替
}
}
可变参数列表可以看作是数组
public void sum(int...n){}
public void sum(int[] n){}//这两个属于重复定义
参数列表中如果有两个或两个以上的参数,可变参数一定是在最后的。
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 void search(int n, int[] a) {
//可变参数方法换成数组是不算重载的,算重复定义
}*/
/*public void search(int n, int... a, int...b) {
//一个方法中只能有一个可变参数。
}*/
public static void main(String[] args) {
ArgsDemo1 ad1=new ArgsDemo1();
ad1.search(3,1,2,3,4,5);
int[] a={1,2,3,4,5};
ad1.search(3,a);//可变参数列表可以和数组进行兼容,可以将数组传递给可变参数列表
}
}
总结:
- 可变参数列表指的是参数数量是不确定的,可以随时变化,有时候也称可变原参数。
- 参数列表中如果有两个或两个以上的参数,可变参数一定是在最后的。例如:public void a(int a,int… b){ }是正确的,但是如果把int… b写前面则是错误的。
- 可以将数组传递给可变参数。
- 一个方法中只能有一个可变参数。
- 可变参数方法换成数组是不算重载的,算重复定义。
可变参数列表作为方法参数的重载问题
public class Demo {
public int sum(int a, int b) {
System.out.println("不带可变参数列表的方法被调用");
return a + b;
}
//求和
public int sum(int...n) {
int sum = 0;
for(int i:n) {//其实我们可以将可变参数列表看作为一个数组
sum = sum + i;
}
System.out.println("带可变参数列表的方法被调用");
return sum;
}
public static void main(String[] args) {
Demo de = new Demo();
System.out.println("和为:" + de.sum(1,2));
System.out.println("和为:" + de.sum(3,4));
System.out.println("和为:" + de.sum(3,4,5));
}
}
总结:
若有多个重载方法,则可变参数列表所在的方法是最后被访问的(如果主方法所传参数其他重载方法可以满足,则调用其他方法,只有其他方法都不满足,才会调用可变参数列表所在的方法)。