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
类的两个对象进行分析
Java |
---|
1
2
3
4
5
6
7
8
9
10
11
12 | package com.epsda.java_class;
public class Person {
// 属性
String name;
int age;
// 方法
public void print(){
System.out.println("name = " + name + " " + "age = " + age);
}
}
|
首先,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
对象,为各个成员赋值打印