Java基础笔记7(方法)

方法定义

  • 方法是语句的集合,它们在一起执行一个功能
    • 方法是解决一类问题的步骤的有序组合
    • 方法包含于类或对象中
    • 方法在程序中被创建,在其他地方被引用
  • 方法是一段用来完成特定功能的代码片段
  • 方法包含一个方法头和一个方法体
    • 修饰符:可选,告诉编译器如何调用该方法。定义了该方法的访问类型
    • 返回值类型:方法返回值的数据类型
    • 方法名:方法的名称,方法名和参数表共同构成方法签名
    • 参数类型:方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含参数
      • 形式参数:在方法被调用时用于接收外界输入数据
      • 实参:调用方法时实际传给方法的数据
    • 方法体:方法体包含具体的语句,定义该方法的功能
1
2
3
4
5
6
修饰符 返回值类型 方法名(参数类型 参数名){
...
方法体
...
return 返回值;
}

方法调用

  • 调用方法:对象名.方法名(实参列表)

  • 方法返回一个值时,方法调用常被当做一个值,如

    1
    double num = Math.pow(2, 3);//8.0
  • 方法返回值是void时,方法调用直接作为一条语句,如

    1
    System.out.println();

值传递和引用传递

  • 值传递:在调用函数时将实际参数复制一份副本传递到函数中,在函数中如果对参数进行修改,将不会影响到实际参数。
  • 引用传递:在调用函数时将实际参数的地址传递到函数中,实参和形参在内存上指向了同一块区域,在函数中对参数所进行的修改,将影响到实际参数。

Java是值传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//例一
public class test {
public static void main(String[] args) {
int s = 10;
change(s);
System.out.println("实参s:" + s);
}

public static void change(int x) {
x++;
System.out.println("形参x:" + x);
}
}
/*
输出:
形参x:11
实参s:10

解释:
x是s的副本,存储空间不同,x改变不影响s
*/
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//例二
//2.1
public class test {
public static void main(String[] args) {
Student s = new Student("张三");
change(s);
System.out.println(s.getName());
}

public static void change(Student x) {
x.setName("李四");
System.out.println(x.getName());
}
}
/*
输出:
李四
李四

解释:
为什么输出相等?实参的值被改变了吗?看下面分析
*/

//2.2
public class test {
public static void main(String[] args) {
Student s = new Student("张三");
System.out.println("change前s的地址:" + s);
change(s);
System.out.println("change后s的地址:" + s);
System.out.println("s所指对象的内容:" + s.getName());
}

public static void change(Student x) {
x.setName("李四");
System.out.println("x的地址:" + x);
System.out.println("x所指对象的内容:" + x.getName());
}
}
/*
输出:
change前s的地址:Student@312b1dae
x的地址:Student@312b1dae
x所指对象的内容:李四
change后s的地址:Student@312b1dae
s所指对象的内容:李四

解释:
我们发现change函数对对象的内容进行了修改,而没有修改对象的地址
继续看下例
*/

//2.3
public class test {
public static void main(String[] args) {
Student s = new Student("张三");
System.out.println("change前s的地址:" + s);
change(s);
System.out.println("change后s的地址:" + s);
System.out.println("s所指对象的内容:" + s.getName());
}

public static void change(Student x) {
x = new Student("李四");
System.out.println("x的地址:" + x);
System.out.println("s所指对象的内容:" + x.getName());
}
}
/*
输出:
change前s的地址:Student@312b1dae
x的地址:Student@7530d0a
s所指对象的内容:李四
change后s的地址:Student@312b1dae
s所指对象的内容:张三

解释:
通过该例我们可以发现,在将对象作为参数传入方法中时,传递的是地址,将对象的地址复制一份副本传给形参。
因此2.1中看似在方法中将张三修改为了李四并影响了实参,实则真正的形参(传入对象的地址)并未修改(见2.2),因此不能说形参影响了实参。
2.3中使形参x指向一个新的对象,修改了形参的内容(x的地址:Student@7530d0a),从输出结果可以看出,实参的值并未受影响(change前s的地址:Student@312b1dae、change后s的地址:Student@312b1dae)
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//例三
public class test {
public static void main(String[] args) {
String s = "a";
change(s);
System.out.println(s);
}

public static void change(String x) {
x = "b";
System.out.println(x);
}
}
/*
输出:
b
a

解释:
String 变量只要被赋值就等于新new一个String对象
因此x += "b";等价于x = new String("b");
*/

方法重载

  • 方法名相同,参数类型不同
  • 方法重载规则
    • 方法名相同
    • 参数列表不同(个数不同、类型不同、顺序不同等)
    • 返回值类型可以相同也可以不同
    • 只有返回值类型不同不能成为方法重载
  • 方法名称相同时,编译器会根据调用方法的参数个数、类型等去匹配方法,匹配失败编译器会报错。

命令行传参

1
2
3
4
5
6
7
public class test {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println("args["+i+"]="+args[i]);
}
}
}
1
2
3
4
5
6
7
8
9
10
E:\test>javac src\test.java

E:\test>cd src

E:\test\src>java test hello world
args[0]=hello
args[1]=world

E:\test\src>

可变参数

  • JDK1.5开始,Java支持传递同类型的可变参数给一个方法
  • 在方法声明中,在指定参数类型后加一个省略号(…)
  • 一个方法中只能指定一个可变参数,它必须是方法最后一个参数,任何普通参数必须在他之前声明
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Test {
public static void main(String[] args) {
Test test = new Test();
test.print(1,2,3,4,4,4);
}

public void print (int... n){
System.out.println(n);
for (int i = 0; i < n.length; i++) {
System.out.println(n[i]);
}
}
}

递归

  • 递归包含两个部分
    • 递归头
    • 递归体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//阶乘
public class Test {
public static void main(String[] args) {
Test test = new Test();
System.out.println(test.factorial(5));//120
}

public int factorial(int n) {
if (n == 0) {
return 1;
} else if (n == 1) {
return 1;
} else {
return n * factorial(n - 1);
}
}
}