Java面向对象与方法
约 1091 个字 287 行代码 2 张图片 预计阅读时间 7 分钟
基本方法
基本定义
在Java中,方法即为函数,Java中的方法定义遵循下面的通用格式
Java |
---|
| 修饰符 返回值 方法名 (形参列表){
方法体
}
|
对于基本方法的定义,遵循下面的结构
Java |
---|
| public static 返回类型 方法名(形参列表){
方法体
}
|
Note
是否需要返回类型和形参列表需要看该函数的功能,具体思路可以参考C/C++中定义函数的方式
Java |
---|
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 | package com.epsda.method;
/**
* ClassName: Test_method
* Package: com.epsda.method
* Description:
*
* @author 憨八嘎
* @version v1.0
*/
public class Test_method {
public static void main(String[] args) {
int ans = add(10, 20);
System.out.println("ans = " + ans);
}
// 示例方法
public static int add(int a, int b){
int sum = a + b;
return sum;
}
}
输出结果:
ans = 30
|
数组类型作为参数
如果是数组类型作为方法参数和返回值时,需要注意,在Java中,传递和返回数组都只是传递地址值
Java |
---|
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 | package com.epsda.method;
/**
* ClassName: Test_method
* Package: com.epsda.method
* Description:
*
* @author 憨八嘎
* @version v1.0
*/
public class Test_method {
public static void main(String[] args) {
int arr[] = {10, 20};
int arr1[] = calculate(arr);
for (int i = 0; i < arr1.length; i++) {
System.out.print(arr1[i]+" ");
}
}
// 数组作为形参和返回值
public static int[] calculate(int[] arr) {
int sum = 0;
int sub = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
sub -= arr[i];
}
int[] arr1 = {sum, sub};
return arr1;
}
}
输出结果:
30 -30
|
可以类比下面的C语言代码
Java |
---|
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 | #include <stdio.h>
#include <stdlib.h>
// 定义calculate函数,返回值为指针类型,参数为指针+输出型参数size(表示数组大小)
int *calculate(int *arr, int *size)
{
int sum = 0;
int sub = 0;
for (int i = 0; i < *size; i++)
{
sum += arr[i];
sub -= arr[i];
}
// 因为C语言数组是在栈上开辟的,所以不能返回,需要返回时必须使用动态内存开辟
int *arr1 = (int *)malloc(sizeof(int) * 2);
arr1[0] = sum;
arr1[1] = sub;
// 改变输出型参数值作为返回数组的长度
*size = sizeof(arr1) / sizeof(int);
return arr1;
}
int main()
{
int arr[2] = {10, 20};
int size = sizeof(arr) / sizeof(int);
int *arr1 = calculate(arr, &size);
for (int i = 0; i < size; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
输出结果:
30 -30
|
方法重载
Java同C++一样,也支持方法重载,并且方式相同
重载要求:
- 参数个数不同
- 参数类型不同
- 在参数个数相同,参数类型不同的情况下,参数顺序不同
满足上面任意一个条件即可构成函数重载
Java |
---|
1
2
3
4
5
6
7
8
9
10
11
12 | // 定义基础方法
public static void test(){}
// 下面函数与基础方法可以构成重载
public static void test(int a){}// 可以
public static void test(int a,int b){}// 可以
public static void test(double a,int b){}// 可以
public static void test(int a,double b){}// 可以
// 下面情况不可以
public static void test(int i,double d){}// 不可以
public static void TEST(){}// 不满足重载前提
public static void test(int i,int j){}// 不可以
public static int test(int a, int b){}// 不可以
|
在Java中,方法重载的实现依靠方法签名,所谓方法签名,就是经过编译器编译修改过之后方法最终的名字。具体表示方式为:方法全路径名+参数列表+返回值类型,构成方法完整的名字,例如下面的代码:
Java |
---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 | public class Test {
// 不同参数数量
public static double add(double a, double b, double c) {
return a + b + c;
}
// 相同参数数量,不同参数类型
public static double add(double a, double b) {
return a + b;
}
// 相同参数数量,不同参数类型
public static int add(int a, int b) {
return a + b;
}
public static void main(String[] args) {
System.out.println(add(1, 2));
System.out.println(add(1.0, 2.0));
System.out.println(add(1, 2, 3));
}
}
|
使用JDK自带的javap
反汇编根据查看当前类对应的字节码文件Test.class
:
反汇编后的结果:
Bash |
---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | ...
#13 = Methodref #14.#15 // Test.add:(II)I // 表示参数为两个int类型,返回值为int类型,位于Test类中的add方法
...
#16 = Methodref #14.#17 // Test.add:(DD)D // 表示参数为两个double类型,返回值为double类型,位于Test类中的add方法
...
#35 = Methodref #14.#36 // Test.add:(DDD)D // 表示参数为三个double类型,返回值为double类型,位于Test类中的add方法
main方法调用:
5: invokestatic #13 // Method add:(II)I // 修饰为函数名:(参数类型描述)返回值类型描述
...
18: invokestatic #27 // Method add:(DD)D // 修饰为函数名:(参数类型描述)返回值类型描述
...
34: invokestatic #35 // Method add:(DDD)D // 修饰为函数名:(参数类型描述)返回值类型描述
...
|
类和对象
类
创建类
在Java中,使用class
关键字创建类,建议一个类作为一个单独的文件
一般称成员变量为属性,称成员函数为方法
例如,Person
类
Java |
---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | package com.epsda.java_class;
/**
* ClassName: Person
* Package: com.epsda.java_class
* Description:
*
* @author 憨八嘎
* @version v1.0
*/
public class Person {
// 属性
String name;
int age;
// 方法,不使用static关键字
public void speak(){
System.out.println("说话");
}
}
|
成员变量(属性)和局部变量的区别
成员变量和局部变量有以下的区别:
- 定义位置不同
- 成员变量定义在方法外,类内,整个类中都可以被访问
- 局部变量定义在方法内,只能在当前最近的作用域中访问
- 初始化值不同
- 成员变量有默认值,默认值参考数组中的类型默认值
- 局部变量没有默认值
- 内存位置不同
- 成员变量预备在方法区,实际使用时在堆区
- 局部变量在栈区
- 生命周期不同
- 成员变量的生命周期随着对象的创建而创建,随着其销毁而销毁
- 局部变量的生命周期随着当前作用域的销毁而销毁
对象
创建对象
在Java中,创建对象需要使用new
关键字,使用new
创建出来的对象都在堆区 例如,创建Person
类对象
Note
如果两个类在同一个包下,则再另一个类中使用当前类创建对象时不需要引包操作,否则需要使用import
关键字引包
特殊地,Java中的lang
包不需要单独引包
两个不同对象的内存分析
以Person
类的两个对象进行分析
首先,Person
类中的属性和方法以及测试类的方法都会加载到方法区进行预备,此时每一个类都会有一个class
地址值

接着,main
方法执行,加载到栈区,创建出对象p1
和p2
,因为是new
为对象开辟的空间,所以该空间在堆上,p1
和p2
分别存储这两个堆上空间的地址,并且在两个对象空间中,都存在着class
地址值,当类相同时,class
地址值也是相同的,该地址值用于查询到类中的方法,执行print
时加载print
方法进入栈区

匿名对象
在Java中,也可以创建匿名对象,前面创建对象的步骤为类名 对象名 = new 类名()
,那么匿名对象即为去无赋值符左边部分new 类名()
Java |
---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | package com.epsda.java_class;
/**
* ClassName: Java_class
* Package: com.epsda.Java_class
* Description:
*
* @author 憨八嘎
* @version v1.0
*/
public class Java_class {
public static void main(String[] args) {
// 创建Person类匿名对象调用函数
new Person().print();
}
}
|
Note
一般在只需要调用函数时创建匿名对象,每一次匿名对象的创建都是重新开辟一块空间
类和对象练习与链式调用
创建一个Birthday
类,该类中有属性year
,month
和day
,再创建一个Person
类,Person
类中有属性name
,age
和birthday
,实例化一个Person
对象,为各个成员赋值打印