java基础(三)

本次记录的是方法,在其他语言也被称为函数。

我们写java代码中,main也是方法。public static void main(String[] args){}。其中public是访问控制修饰符,static是非访问修饰符,也称为静态修饰符,void是返回值类型,String[]是参数类型,为字符串数组(要区别字符数组char[]),args是参数名。

为什么要使用方法,为了更好的调用,减少代码冗余度,避免不必要的浪费,也为了减少代码修改的次数。

方法的定义

1
2
3
4
修饰符 修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2...){
代码;
return 返回值;
}

修饰符

修饰符:告诉编译器这个方法如何使用。方法中有四个访问控制修饰符:,public、protected、default、private。和两个基本非访问修饰符:final和static。

访问控制修饰符

public:公有访问修饰符。可以被所有类访问。

protected:受保护富访问修饰符。对同一包内的类和所有子类使用。

default:默认修饰符。在同一个包内可见。

private:私有访问修饰符。只能是当前类使用。

以default为例,在java中,不是静态方法或类,都要先new一个对象,才能使用相应的方法或类。其它修饰符也可以做,使用不同的包建立class,感受这些修饰符感受差异。

1
2
3
4
5
6
7
8
9
public class FangfaTest {
public static void main(String[] args) {
FangfaTest ff = new FangfaTest();
System.out.println(ff.add(1,2));
}
int add(int a, int b) {
return a+b;
}
}

而public和private应该是最常用的修饰符吧,使用的次数挺多的。当然,这里强调下,在一个类中,只能有唯一一个public类,但可以有多个public方法。

非访问修饰符

static:静态修饰符,静态变量和方法可是直接使用。

final:变量一旦赋值,就不能更改,和static使用创建类常量。

static修饰的方法直接使用,不需要创建对象。常用的类Math也是静态类,它里面有很多方法也是静态方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class FangfaTest {
static int a = 1; //静态修饰的变量
final int B = 2; //final修饰的变量,也称为常量,不能更改值

public static void main(String[] args) {

System.out.println(add(1,2)); //使用static修饰的方法
a = 2; //修改static修饰的变量
// B= 3; final修饰的常量不能更改值,修饰的类也不能继承
System.out.println(a);

FangfaTest ff = new FangfaTest();
System.out.println(ff.add(1.2,2)); //只要不是static修饰的方法,都要先new一个对象
}

//下面是方法重载,返回值类型和参数类型不同
final double add(double a, double b) {
return a+b;
}

static int add(int a, int b) {
return a+b;
}
}

以上六种修饰符,不仅可以用在方法上,也可以用在类或类里的数据类型上。当然,修饰符还有其它的,那就要讲到后面的内容慢慢补充。

方法的返回类型

方法的返回也就是我们前面记录的八种基本数据类型和现在慢慢补充的引用类型,比如数组,以后的字符串String或者是类。还有无返回类型void。

用基本数据类型int实例:

1
2
3
4
5
6
7
8
9
10
public class FangfaTest {
public static void main(String[] args) {
FangfaTest ff = new FangfaTest();
System.out.println(ff.add(1,2));
}

int add(int a, int b) {
return a+b;
}
}

返回类型为void实例:

1
2
3
4
5
6
7
8
9
10
11
public class FangfaTest {
public static void main(String[] args) {
FangfaTest ff = new FangfaTest();
ff.add(1,2);
}

void add(int a, int b) {
System.out.println(a+b);
return; //虽然没返回值,但return有两个意思,一个结束运行,另一个返回结果。在这只是结束运行。
}
}

用类简单写了一个1+2,然后用方法调用:

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
public class FangfaTest {
public static void main(String[] args) {

//先把对象建立,两个类,两个对象
FangfaTest ff = new FangfaTest();
adds a = new adds();

//设置私有变量a和b的值
a.setA(1);
a.setB(2);

//输出结果
System.out.println(ff.add(a));

}
//公有类的方法
int add(adds a) { //调用了adds类
return a.add();
}
}

//类的封装,我可以在set方法中设置我的要求,比如是正整数呀,范围多少,增加限制,减少代码出错率
class adds{
private int a;
private int b;

public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}

public int getB() {
return b;
}
public void setB(int b) {
this.b = b;
}

public int add() {
return this.a+this.b; //关键字this,指当前的类的变量
}
}

方法的重载

重载,意思就是实现的内容大致一样,只是参数类型不同,返回类型无所谓,但参数类型一定要不一样,否则,编译器不知道用谁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Test02 {
public static void main(String[] args) {

Test02 t = new Test02();

System.out.println(t.add(1, 2));
System.out.println(t.add(1, 2, 3));
System.out.println(t.add(1.2, 2.1));

}
int add(int a,int b) {
return a+b;
}
int add(int a,int b, int c) {
return a+b+c;
}
double add(double a, double c) {
return a+c;
}
}

如果把double add()里的参数类型都变成int,那就会编译器报错。所以一定是参数类型不同才能重载。

值传递与引用传递

形参:方法中定义的参数。

实参:调用中,传入方法的实际参数。

值传递:只是把值传给方法的参数,但不改变原参数的值。一般只有八种基本数据类型是值传递。

引用传递(址传递):传入方法中,如果方法里的参数改变了数据,那么原参数也改变。一般只是引用类型会改变。

为什么会有值传递和址传递的差异?

说白了就是指向的对象不同,值传递是在方法调用中,指向一个新的数据变量,址传递因为一开始都指向同一个对象,那么原参数也改变。

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
import java.util.Arrays;

public class test03 {
public static void main(String[] args) {
//基本数据类型,一般是值传递
int a = 10; //一开始a是10
changeInt(a); //方法里把a变为20
System.out.println(a); //值传递并没有改变原a的值

//引用类型,一般是引用传递/址传递
int []arr = new int[] {0,1,2,3,4,5,6,7,8,9};
changeArr(arr); //数组是一个对象,改变同对象的值
System.out.println(Arrays.toString(arr));

//方法中重新new一个对象
changeArr2(arr); //新的方法,重新new一个数组[0,1,2,3,4]
System.out.println(Arrays.toString(arr)); //但并没有改变原数组的值,因为它们的指向的地址不同

}

public static void changeInt(int a) {
a = 20;
}
public static void changeArr(int a[]) {
for(int i=0; i<a.length; i++) {
a[i] = (i+1)*2;
}
}
public static void changeArr2(int a[]) {
a = new int [5]; //新new一个数组
for(int i=0; i<a.length; i++) {
a[i] = i;
}
}
}

方法块

上面讲的都是有返回类型,方法名的方法,如果没有呢?那就是方法块。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Test {

static {
System.out.println("static方法块");
}

{
System.out.println("main外的方法块");
}
public static void main(String[] args) {

System.out.println("main方法");
{
int a = 10;
System.out.println("main里的方法块");
}
//a = 5;
}
}

由于没有方法名,所以只能直接放到main里使用,而且方法块里的变量,属性,在方法块外是没发使用的,相当于局部变量。

1
2
3
static方法块
main方法
main里的方法块

结果是不是很意外,分析一下,在执行程序时,先将静态的,类,方法名,常量放到内存的方法区,所以先加载static方法块,然后执行main方法,一步一步执行,为啥没执行main外的方法块呢,因为我们没调用这个类。下次再继续。

方法就这么多记录,有遗漏欢迎在评论区补充,有不足也请多多关照,在评论区留言,也感谢您的观看,下次见。

谢谢您对我的支持
0%