方法概述
所谓方法,就是用来解决一类问题的代码的有序组合,是一个功能模块
作用:封装重复逻辑,逻辑更清晰
语法格式:
访问修饰符 返回类型 方法名(参数列表){
方法体
}
访问修饰符:允许被访问的权限范围,可以是public/private/default/protected
返回类型:可以是void(无返回值) 以及任何数据类型,带返回值方法使用return语句进行返回。
参数列表:传递给方法的参数列表,可省略,参数可以有多个,以逗号分隔,每个参数由参数类型及参数名组成。
根据方法是否带参数、是否带返回值,可分为四类:
Ø 无参无返回值方法
Ø 无参带返回值方法
Ø 带参无返回值方法
Ø 带参带返回值方法
无参无返回值方法
如果方法不包含参数,且没有返回值,我们称为无参无返回值的方法。
该方法的返回类型为void,且方法中不能使用return返回值!(可以单独使用return;)
public class HelloMethod {
//定义方法
public void show(){
//方法体
System.out.println("welcome to learn java");
}
public static void main(String[] args) {
//创建一个HelloMethod类的对象hello
HelloMethod hello = new HelloMethod();
//使用对象名.方法名()去调用方法
hello.show();
}
}
无参带返回值方法
如果方法不包含参数,但有返回值,我们称为无参带返回值的方法。
返回使用return语句,返回的数据类型要与方法声明的返回类型相匹配(兼容)。
public class HelloMethod {
//定义求长方形面积的方法
public int getArea(){
int length = 10, width = 5;
return length * width; //返回语句
}
public static void main(String[] args) {
HelloMethod hello = new HelloMethod();
//打印返回值,或者可以定义变量接收返回值:int area = hello.getArea();
System.out.println("长方形的面积为:" + hello.getArea());
}
}
带参无返回值方法
可以通过在方法中加入参数列表接收外部传入的数据信息,来完成特定的功能实现。
参数可以是任意的基本类型数据或引用类型数据,调用带参方法时,必须保证实参的数量、类型、顺序与形参一一对应。
形参:我们把定义方法时的参数称为形参,目的是用来定义方法需要传入的参数的个数和类型
实参:把调用方法时的参数称为实参,是传递给方法真正被处理的值
实参可以传递变量或者字面值,当传递变量时变量名不需要与形参名相同
public class HelloMethod {
//输出两个数的最大值
public void max(float a, float b){
float max = a > b ? a : b;
System.out.println("两个数" + a + "和" + b + "的最大值为:" + max);
}
public static void main(String[] args) {
HelloMethod hello = new HelloMethod();
int a = 3, b = 5;
hello.max(a, b); //可以传递int值,因为可以自动转换为float型
float m = 5.6f, n = 3.4f;
//传递实参名
hello.max(m, n);
//传递字面值
hello.max(6.6f, 3.3f);
//hello.max(1.2, 3.4); 错误,不能传递double类型
}
}
带参带返回值方法
如果方法既包含参数,又带有返回值,我们称为带参带返回值的方法。
public class HelloMethod {
//求阶乘的方法
public int factorial(int num){
int s = 1;
for (int i = 1; i <= num; i++) {
s *= i;
}
return s;
}
public static void main(String[] args) {
HelloMethod hello = new HelloMethod();
int fac = hello.factorial(5);
System.out.println("5! = " + fac); //120
int sum = 0;
//求1! + 2! + 3! + 4! + 5!
for (int i = 1; i <= 5; i++) {
fac = hello.factorial(i);
sum += fac;
}
System.out.println("1!+2!+3!+4!+5!=" + sum); //153
}
}
方法重载
如果同一个类中包含了两个或两个以上方法名相同、方法参数的个数、顺序或类型不同的方法,则称为方法的重载。
特点:同一个类中,方法名相同,参数列表不同(参数类型或者参数个数或者参数顺序),与方法修饰符和返回值无关
好处:对于具有相同功能的方法可以重用方法名,使其更符合语义
//求两个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 += arr[i];
}
return sum;
}
public static void main(String[] args) {
HelloMethod hello = new HelloMethod();
int a = 5, b = 10;
int[] arr = {1,2,3,4,5};
//当调用被重载的方法时, Java会根据参数的个数和类型来判断应该调用哪个重载方法,参数完全匹配的方法将被执行
System.out.println("int类型的和为:" + hello.plus(a, b));
System.out.println("double类型的和为:" + hello.plus(5.6, 3.4));
System.out.println("数组元素的和为:" + hello.plus(arr));
}
方法传值问题
基本数据类型的参数传递
基本数据类型的参数传递属于值传递,即方法调用时,实际参数把它的值传递给对应的形式参数,函数接收的是原始值的一个copy,在方法的内部改变参数的值并不会影响传递进来的外部对象。
public class HelloMethod {
//基本数据类型的参数传递
public void add(int n){
n++;
System.out.println("方法中n=" + n);
}
public static void main(String[] args) {
int n = 10;
HelloMethod hello = new HelloMethod();
hello.add(n);
System.out.println("方法调用后n的值:" + n);
//方法中n=11
//方法调用后n的值:10
}
}
引用类型的参数传递
引用类型的参数传递属于引用传递,方法调用时,实际参数的引用(地址)被传递给方法中相对应的形式参数,函数接收的是原始值的内存地址,此时方法参数和实参指向了同一个内存空间。
a) 如果在函数中没有改变这个引用地址,而是改变了地址中的内容,那么在函数内的改变就会影响到传入的实际参数。
b) 如果在函数中改变了引用地址,比如重新new一个,那么形参就指向了一个新的地址,此时传入的参数还是指向原来的地址,所以函数内的改变不会影响到传入的实际参数。
public class HelloMethod {
//引用类型的参数传递
public void updateArray(int[] a){
a[3] = 15;
}
//引用类型的参数传递
public void updateArray2(int[] a){
a = new int[a.length]; //a重新指向了新的内存空间(地址)
a[3] = 20;
}
public static void main(String[] args) {
HelloMethod hello = new HelloMethod();
int[] a1 = {1,2,3,4,5}, a2 = {1,2,3,4,5};
hello.updateArray(a1);
System.out.println("方法调用后数组元素为:");
for (int n : a1) {
System.out.print(n + " ");
}
System.out.println();
//方法调用后数组元素为:
//1 2 3 15 5
hello.updateArray2(a2);
System.out.println("方法调用后数组元素为:");
for (int n : a2) {
System.out.print(n + " ");
}
System.out.println();
//方法调用后数组元素为:
//1 2 3 4 5
}
}
特别注意包装类以及String类(后续介绍)的不可变性,也就是说对它们的值的改变实际上都是创建新的对象。
public void append(String str){
str += " hehe"; //str指向了新的字符串对象
}
public static void main(String[] args) {
HelloMethod hello = new HelloMethod();
String str = "hello";
hello.append(str);
System.out.println(str); //hello
}
可变参数列表
- 参数数量不确定,可以随时变化,可变参数的本质是一个数组,会将传入的多个参数转成一个数组,而参数名就是数组引用,所以可以使用索引访问参数列表。
- 可变参数与数组类型不能重载,因为二者本质上是一样的。
- 方法如果有多个参数时,可变参数必须放在最后。
- 可以将数组传递给可变参数列表,但是数组作为参数时,是不能将多个值传递给数组的!
- 可变参数列表所在的方法是最后被访问的,如果有其他匹配的方法,会优先执行。
public class HelloMethod {
//可变参数
public int plus(int... a){
System.out.println("带可变参数的方法被调用");
int sum = 0;
for(int n : a){
sum += n;
}
return sum;
}
//重载方法
public int plus(int a, int b){
System.out.println("不带可变参数的方法被调用");
return a + b;
}
//多个参数,可变参数放在最后
public int search(int a, int... arr){
for (int i = 0; i < arr.length; i++) {
if(arr[i] == a){
return i;
}
}
return -1;
}
public static void main(String[] args) {
HelloMethod hello = new HelloMethod();
//优先匹配不带可变参数方法
hello.plus(1, 2);
//传递数组
int[] a = {1,2,3,4,5,6};
hello.plus(a);
//可变参数方法调用
System.out.println("和为:" + hello.plus(1,2,3,4,5,6));
/*不带可变参数的方法被调用
带可变参数的方法被调用
带可变参数的方法被调用
和为:21
*/
}
}