智渔课堂官方免费教程八:Java基础之方法(函数)

时间:2022-01-18 23:33:11

方法(C语言中称为函数)

方法:由多条语句组成,可以重复使用的,完成一个或多个功能的代码集合;方法只能声明在类中,不能声明在其他方法中
语法格式:
[访问修饰符] 返回值类型 方法名([参数列表]){
 //代码块 

注:这里的中括号[]代表括号里的内容可以写也可以不写,如果写,中括号不用写
例如:
/**
* 演示方法的声明和调用
* @author 学霸联盟 - 赵灿
*/
public class MethodDeclareDemo {
/**
* 声明了一个没有参数的方法,方法名为m1
* 方法体也是空的,表示这个方法什么都没做
*/
void m1(){}
/**
* 声明了一个带两个参数的方法,方法名为m2
* 这里的两个参数,本质就是声明变量,称为形式参数,简称形参
* 当这个方法被调用时,按照形参的顺序,传入对应数据类型的值或变量
* 被传入的值称为实际参数,简称形参
* 该方法的方法体中有一条输出语句,输出传入两个参数的值,这就是方法的功能
*/
void m2(String name, int age){
System.out.println("姓名:" + name + " 年龄:" + age);
}
/**
* 这也是一个方法,方法名是main,有一个String[]类型的参数
* 只不过这个方法比较特殊,是程序的入口
*/
public static void main(String[] args){
//创建一个MethodDeclareDemo类的对象
MethodDeclareDemo mdd = new MethodDeclareDemo();
//调用方法m1,m1这个方法什么都没有做
mdd.m1();
/*
* 调用方法m2,由于m2声明了参数,调用时必须传入实参
* "张三"和18就是传递给方法m2的实参
* 参数传递过程相当于赋值操作
* 程序执行mdd.m2("张三", 18);这条语句时
* 会将"张三"赋值给形参name(相当于String name = "张三")
* 18赋值给形参age(相当于int age = 18)
*/
mdd.m2("张三", 18);
}
}
运行结果:姓名:张三 年龄:18
方法的参数:就是在方法的小括号中声明的变量,这个变量称为:形式参数,简称:形参;用于接收调用时传入的值(实参),形参的使用范围是整个方法,多个参数中间用英文格式的逗号隔开;当带有参数的方法被调用时,必须对应方法声明时编写的参数类型和顺序,给这个方法传入实际的值;这个实际值称为实际参数(简称:实参);
返回值类型:必须写,如果一个方法不需要返回值,返回值类型写void
返回值:方法执行完毕后,返回给调用者的结果;使用关键字return返回,并且返回的值要和返回值类型匹配;格式:return 返回值; 
关键字return:用在方法中,作用是结束整个方法;

例如:某人要去手机店买一部手机,那么他需要先给钱,然后获得手机。其中给的钱就是实参,手机就是返回值
实例:
/**
* 样式方法的返回值类型和返回值
* @author 学霸联盟 - 赵灿
*/
public class Person {
/*
* 声明一个方法名为buy的方法,有一个类型为double的形式参数money
* 返回值的类型是String,那么在方法中必须使用关键字return,返回一个String类型的值
*/
String buy(double money) {
// 声明String类型的变量phone
String phone;
// 判断传入的钱是否大于6000
if (money > 6000) {
// 如果大于6000,就给变量phone赋值为“苹果手机”
phone = "苹果手机";
} else {
// 如果不大于6000,就给变量phone赋值为“华为手机”
phone = "华为手机";
}
/*
* 因为当程序执行到方法调用语句时,程序会跳转到被调用的方法中执行
* 当方法被执行完之后,又会返回到方法调用语句处
* 所以方法中使用关键字return返回的结果被称为返回值
* 当方法声明的返回值类型不是void时,方法中必须使用return语句返回一个返回值
* 此处phone就是返回值
*/
return phone;
}
/*
* 声明一个不带参数的方法,方法名为call
* 声明返回值类型为void代表这个方法没有返回值
* 方法中也可以写return语句,也可以不写
* 如果写return后面只能跟英文格式的分号; 即:return;
*/
void call() {
/*
* 此处声明一个String类型的变量myPhone,来接收buy方法的返回值
* 因为buy的返回值类型是String,所有此处用String类型的变量接收
* 相当于String myPhone = phone(buy方法中return后面的phone)
* 当程序执行buy(1000.0);语句调用buy方法时,程序会跳到buy方法中执行
* 直到遇到buy方法中的return语句后
* 再返回到此处执行赋值语句(将buy方法返回的结果赋值给变量myPhone)
*/
String myPhone = buy(1000.0);
System.out.println("使用\"" + myPhone + "\"拨打电话...");
/*
* return语句可有可无
* 需要注意的是,执行return语句后方法就结束了
* 所以return语句后面还有语句的话就不会被执行
*/
return;
//以下位置(此处开始至方法的右大括号之间)再写代码就会提示错误
}

public static void main(String[] args) {
//创建一个人类的对象
Person person = new Person();
/*
* 程序由main方法进入执行
* 执行到此处调用call方法,程序会跳到call方法中执行
* 当call方法中遇到return或所有代码都执行完成(未写return语句时)后
* 再回到当前位置,执行后面的输出语句
*/
person.call();
//call方法执行完成后,继续执行此句
System.out.println("main方法的最后一句代码");
}
}
运行结果:
使用"华为手机"拨打电话...
main方法的最后一句代码

方法调用语句

语法格式: 对象名.方法名();或 类名.静态方法名();(下面讲到) 
例如上例中用到的 person.call();

方法传参

值传递(基本数据类型)

将实参变量中保存的值复制一份,赋值给形参变量;赋值之后实参变量和形参变量没有任何关系,修改任何一个变量,另一个变量都不会发生变量

引用传递(引用类型,String除外)

将实参变量中存储的对象的内存地址复制一份赋值给形参变量,此时实参变量和形参变量中保存的是同一个对象的内存地址;使用任何一个引用对对象的属性进行修改,再次使用任何一个引用访问对象被修改的属性时都会发生变化。
/**
* 声明汽车类Car
* @author 学霸联盟 - 赵灿
*/
class Car{
//声明一个String类型的变量name
String carName;
//声明一个变量color代表汽车的颜色,并赋值
String color = "无色";
}
/**
* 声明汽车工厂类CarFactory
* @author 学霸联盟 - 赵灿
*/
class CarFactory{
/**
* 声明一个结账的方法
* 用于测试参数的值传递
* 参数money用于接收用户付款
*/
void settlement(double money){
System.out.println("用户付款:" + money);
//修理费150
double repairs = 150;
//对变量money进行修改,得到收取修理费剩余的钱
money = money - repairs;
System.out.println("应找零:" + money);
}
/**
* 声明一个修改汽车颜色的方法
* 用于测试参数的引用传递
* 参数car用于接收被修改颜色的汽车
*/
void setColor(Car car) {
// 将接收到的汽车的颜色设置成黑色
car.color = "黑色";
}
}

/**
* 演示值传递和引用传递
*
* @author 学霸联盟 - 赵灿
*/
public class ParameterTransferDemo {
// 声明一个main方法,作为程序的入口
public static void main(String[] args) {
System.out.println("------------ 引用传递 ------------");
//使用关键字new创建汽车对象,并将对象在内存中的地址赋值给变量c
Car c = new Car();
c.carName = "小c";
System.out.println("刚刚创建出来的汽车\"" + c.carName + "\"的颜色是:" + c.color);
//创建汽车工厂对象cf
CarFactory cf = new CarFactory();
//引用传递:将变量c中存储的地址,传递给setColor方法的参数car
cf.setColor(c);
//输出结果汽车的名字还是小c,这表明汽车还是原来的汽车,但是颜色已经变了
System.out.println("通过汽车工厂修改后\"" + c.carName + "\"的颜色是:" + c.color);

System.out.println("------------- 值传递 -------------");
double myMoney = 200;
System.out.println("付款前我的钱是:" + myMoney);
//值传递:调用结算的方法settlement,将myMoney的值传给参数money
cf.settlement(myMoney);
System.out.println("付款后我的钱是:" + myMoney);

/*
* 前面说过,方法的传参相当于用实参给形参赋值
* 下面这段代码中,变量c1代表上面的变量c
* 变量c2代表setColor方法中的参数car
*/
System.out.println("------------ 引用传递 ------------");
//创建一个汽车对象,并将汽车对象在内存中的地址赋值给变量c1
Car c1 = new Car();
//设置名称
c1.carName = "小c1";
//由于引用类型变量中存储的是对象在内存中的地址
//所以引用类型的变量也称为引用
Car c2 = c1;
System.out.println("修改前汽车c1的名称:" + c1.carName + " 颜色:" + c1.color);
System.out.println("修改前汽车c2的名称:" + c2.carName + " 颜色:" + c2.color);
//对c2的修改会影响c1,c1跟着变化
c2.color = "黑色";
System.out.println("修改后汽车c1的名称:" + c1.carName + " 颜色:" + c1.color);
System.out.println("修改后汽车c2的名称:" + c2.carName + " 颜色:" + c2.color);

System.out.println("------------- 值传递 -------------");
double m1 = 200;
double m2 = m1;
System.out.println("修改前m1的值:" + m1);
System.out.println("修改前m2的值:" + m2);
//对m2的修改不会影响m1
m2 = m2 - 150;
System.out.println("修改后m1的值:" + m1);
System.out.println("修改后m2的值:" + m2);
}
}
运行结果:
------------ 引用传递 ------------
刚刚创建出来的汽车"小c"的颜色是:无色
通过汽车工厂修改后"小c"的颜色是:黑色
------------- 值传递 -------------
付款前我的钱是:200.0
用户付款:200.0
应找零:50.0
付款后我的钱是:200.0
------------ 引用传递 ------------
修改前汽车c1的名称:小c1 颜色:无色
修改前汽车c2的名称:小c1 颜色:无色
修改后汽车c1的名称:小c1 颜色:黑色
修改后汽车c2的名称:小c1 颜色:黑色
------------- 值传递 -------------
修改前m1的值:200.0
修改前m2的值:200.0
修改后m1的值:200.0
修改后m2的值:50.0

构造方法(构造器)

使用new关键字创建对象时会被调用,一般用于初始化类中的一些变量。
语法格式: [访问修饰符] 类名([参数列表]){ //方法体 }
实例:
/**
* 演示构造方法
* @author 学霸联盟 - 赵灿
*/
public class CustomerDemo {
String name;
/**
* 构造方法的方法名必须严格和类名一致
* 不能有返回值类型
* 如果不写,系统自动提供一个没有参数的构造方法
* 如果写了,无论写的构造方法带不带参数,系统都不再系统无参构造
*/
CustomerDemo(String str) {
//初始化:第一次赋值
name = str;
}

public static void main(String[] args) {
/*
* 通过new创建对象时,会先将变量name加载到内存中,然后执行构造方法
* 由于在CustomerDemo类中声明了带一个String类型参数的构造方法
* 所以系统将不会再为CustomerDemo类提供无参的构造方法了
* 所以使用new创建对象时必须传入参数
*/
CustomerDemo cd = new CustomerDemo("abc");
//输出结果:abc
System.out.println(cd.name);
}
}
运行结果:abc
注意: 1、没有返回值类型,方法名和类名完全一致(包括大小写也必须一致)
2、使用new创建对象时,先将在堆中创建一块内存空间,将属性加载到这块内存空间中,然后执行构造方法
3、如果不写构造方法,系统会自动提供一个无参的构造方法
4、如果写了构造方法,系统将不再提供无参构造
5、如果构造方法前写了返回值类型,该方法便不是构造方法了,只不过是一个名字和类名相同的普通方法


构造方法和普通方法的区别

1、 返回值类型:构造方法没有返回值类型,普通方法必须有(如果不需要返回值,写void)
2、 方法名:构造方法的方法名和类名完全一致(包括大小写也必须一致),普通方法的方法名自定义
3、 构造方法可以使用关键字this、super调用,new操作时也会调用,普通方法是用对象名.方法名();的方法调用
4、 一个类中,如果不写构造方法,系统会自动提供一个无参的构造方法;如果写了构造方法,系统将不再提供无参构造;
5、 如果构造方法前写了返回值类型,该方法便不是构造方法了,只不过是一个名字和类名相同的普通方法

方法的重载:@Overload

方法重载是描述同一个类中,相同方法名之间的关系。
无论是普通方法还是构造方法,都可以被重载。
例如:一个类中包含多个构造方法和多个同名的方法
/**
* 演示方法的重载(overload)
* @author 学霸联盟 - 赵灿
*/
public class OverloadDemo {
String str;
/*
* 创建了两个构造方法,这两个构造方法就构成了重载
*/
OverloadDemo(){}
OverloadDemo(String s){
str = s;
}

/*
* 创建了两个普通方法
* 两个方法的方法名相同,参数列表不同
* 他们也构造了方法重载
* 但是如果两个方法名相同,参数列表也相同,就会导致方法同名的错误
*/
void m1(){}
void m1(String s){
str = s;
}

public static void main(String[] args) {
//这种方式创建对象时会调用类的无参构造
OverloadDemo od1 = new OverloadDemo();
//这种方式创建对象,会调用类中带一个String类型参数的构造方法
OverloadDemo od2 = new OverloadDemo("abc");
//输出结果:null
System.out.println(od1.str);
//输出结果:abc
System.out.println(od2.str);
}
}
运行结果:
null
abc

方法重载需要满足的条件:

1、在同一类中
2、方法名相同
3、参数列表不同