参考教程

JDK8帮助文档

狂神说Java视频

方法的概念

QQ截图20201230213450

Demo:

1
2
3
4
5
6
7
8
9
10
11
12
public class Base {
//main方法
public static void main(String[] args) {
int sum = add(1,2);//实参在此
System.out.println(sum);
}

//加法
public static int add(int a, int b){//形参在此
return a+b;
}
}

与C中函数的区别:函数(function)是面向过程的叫法,方法(method)是面向对象的叫法。

方法定义

1
2
3
4
5
6
修饰符 返回值类型 方法名(参数类型 参数名){
...
方法体
...
return 返回值;
}
  • 修饰符:可选,告诉编译器如何调用该方法。定义了该方法的访问类型。
  • 返回值类型:方法可能会返回值。returnValueType 是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType 是关键字void。
  • 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
  • 参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
    • 形参:在方法被调用时用于接收外界输入的数据。用来定义作用的。
    • 实参:调用方法时实际传给方法的数据
    • 实际参数和形式参数的类型要对应!
  • 方法体:方法体包含具体的语句,定义该方法的功能。
1
2
3
4
5
6
7
8
9
10
11
12
//比大小
public static int max(int num1,int num2){
if (num1==num2){
return 0;//常用于终止方法
}

if (num1>num2){
return num1;
} else{
return num2;
}
}

break与return的区别:

  • break:跳出switch,结束循环
  • return:结束方法,返回一个结果

方法调用

1
对象名.方法名(实参列表)

根据方法是否有返回值,有两种调用方法的方式:

  • 返回一个值时,方法调用被当作一个值,定义一个变量去接收这个值;
  • 返回值是void时,方法调用一定是一条语句。

静态方法与非静态方法的调用

调用另一个类里的方法:

1
2
3
4
5
6
7
8
9
10
11
public class StaticLearn {
public static void main(String[] args) {
//静态方法:直接调用
Student.static_say();

//非静态方法:需要先实例化方法所属的这个类(通过new关键字)
//对象类型 对象名 = 对象值
Student student = new Student();
student.unstatic_say();
}
}
1
2
3
4
5
6
7
8
9
10
11
public class Student {
//静态方法
public static void static_say(){
System.out.println("静态说话");
}

//非静态方法
public void unstatic_say(){
System.out.println("非静态说话");
}
}

在同一个类里的互相调用:

1
2
3
4
5
6
7
8
9
10
11
12
   //和类一起加载
public static void a(){
//不可以在这里直接调用b方法:b(); ×
/*
因为static关键字的静态方法随类一起加载,
非静态方法需要在类实例化后才加载,
一个已经存在的东西调用一个不存在的东西会报错
*/
}

//类实例化后才存在
public void b(){}

CSDN博客:静态方法和非静态方法的区别是什么

值传递与引用传递

Java中方法参数传递方式永远是值传递

如果参数是基本类型,传递的是基本类型的字面量值的拷贝。
如果参数是引用类型,传递的是该参量所引用的对象在堆中地址值的拷贝。

Java is Pass by Value and Not Pass by Reference

知乎:Java到底是值传递还是引用传递

证明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//值传递
public class Value {
public static void main(String[] args) {
int a = 1;
System.out.println(a);

Value.change(a);
System.out.println(a);//仍然输出1
}

public static void change(int a){//改的是形参的值,不是实参
a = 10;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//引用传递:传递的是对象,本质还是值传递
public class Refer {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name);//null

Refer.change(person);
System.out.println(person.name);//Messi
}

public static void change(Person person){
//person是一个对象,指向Person person = new Person();是一个具体的人,可以修改属性
person.name = "Messi";//在改下面Person类里的name的值
}
}

//定义了一个Person类,有一个name属性
class Person{
String name;
}

引用传递传递的是对象的地址。

方法重载

重载:在一个类中有相同的函数名称,但形参不同的函数。

重载规则:

  • 方法名称必须相同。
  • 参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等都算不同)。
  • 方法的返回类型可以相同也可以不相同。
  • 仅仅返回类型不同不足以成为方法的重载。

实现理论:方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配(匹配完全看参数列表,不管调用方法时用于接收返回值的变量类型),以选择对应的方法,如果匹配失败,则编译器报错。

命令行传参

1
2
3
4
5
6
7
public class CommandLine {
public static void main(String[] args) {
for (int i=0; i< args.length; i++){
System.out.println("args["+i+"]: "+args[i]);
}
}
}

在运行一个程序时再传递给它消息,要靠传递命令行参数给main()函数实现。

1
2
3
4
5
6
7
8
9
10
D:\Java\code\JavaSE_learning\grammar\src\method>javac CommandLine.java

D:\Java\code\JavaSE_learning\grammar\src\method>cd ..

D:\Java\code\JavaSE_learning\grammar\src>java method.CommandLine

D:\Java\code\JavaSE_learning\grammar\src>java method.CommandLine this is GOAT
args[0]: this
args[1]: is
args[2]: GOAT

可变参数

  • JDK1.5之后支持:传递同类型的可变参数给一个方法
  • 在方法声明中,在指定参数类型后加一个省略号(…)
  • 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数,任何普通参数必须在它之前声明。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class VariableArgs {
public static void main(String[] args) {
VariableArgs variableArgs = new VariableArgs();
variableArgs.test(1,2,3,4);

//找出最大值
printMax(33,434,11,34.2,8.4,123.3,0.34);
printMax(new double[]{1, 2.3, 41, 2.4, 3});
}

public void test(int... i){
System.out.println(i[0]);
System.out.println(i[2]);
System.out.println(i[3]);
}

public static void printMax(double... numbers){
if (numbers.length == 0){
System.out.println("No argument passed.");
return;//代表结束当前方法,直接返回
}

double result = numbers[0];

//排序
for (int i = 1; i < numbers.length; i++) {
if (numbers[i] > result){
result = numbers[i];
}
}

System.out.println("The max value is "+result);
}
}

递归

递归:方法自己调用自己

用处:利用递归可以用简单的程序来解决一些复杂的问题。 它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。

递归结构:

  • 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。
  • 递归体:什么时候需要调用自身方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Recursion {
public static void main(String[] args) {
System.out.println(f(5));
}

//递归求阶乘
public static int f(int n){
if (n==1){
return 1;
}else {
return n*f(n-1);
}
}
}

慎用Java递归调用