9、Java 成员方法详解

写了一段时间的 Java 程序,SpringBoot 项目也做了好几个,但感觉自己对 Java 的了解还是特别少,所以决定从开始重新学习,下面是学习的笔记。【学习素材:韩顺平老师】

我会把我的学习过程分为六个阶段:
① Java 和基于 Java 的编程基础(包括 Java 的基本介绍、变量和运算符、程序控制结构、数组、排序、查找)
② Java 的面向对象编程详解
③ 枚举注解、异常、常用类
④ 集合、泛型、多线程
⑤ IO 流和网络编程
⑥ 反射和正则表达式

文章目录

  • 一、成员方法简单使用
  • 二、方法的调用机制
  • 三、成员方法的好处
  • 四、方法传参机制

一、成员方法简单使用

⛄️ 在【官方教程解释类和对象】这篇文章中说到:就像现实世界的对象中有状态行为一样,Java 编程中的对象也有【行为】,在 Java 编程中对象的行为被叫做【成员方法(简称方法)】

需求:创建 Person 类,提供【做自我介绍】的方法

9、Java 成员方法详解_第1张图片

public class Person {
    private String name;

    /**
     * 做自我介绍(成员方法)
     */
    public void selfIntroduce() {
        System.out.println("你好, 我叫杨嘉立。杨树的杨, 嘉奖的嘉, 立正的立。");
    }

}
public class Main {

    public static void main(String[] args) {
        Person person = new Person();
        // 你好, 我叫杨嘉立。杨树的杨, 嘉奖的嘉, 立正的立
        person.selfIntroduce();
    }

}

创建 Calculator 类, 提供以下3个方法:
(1) 计算 [1, 100] 的累加和
(2) 计算 [start, end] 的累加和
(3) 计算任意个整数的累加和

/**
 * 计算类(用于做各种计算)
 */
public class Calculator {

    /**
     * 计算 [1, 100] 的累加和
     */
    public int sumOne2Hundred() {
        int start = 1;
        int end = 100;
        int sum = 0;
        for (int i = start; i <= end; i++) {
            sum += i;
        }
        return sum;
    }

    /**
     * 计算 [start, end] 的累加和
     */
    public int sumStart2End(int start, int end) {
        int sum = 0;
        for (int i = start; i <= end; i++) {
            sum += i;
        }
        return sum;
    }

    /**
     * 计算提供的多个整数的累加和
     *
     * @param ints 提供的多个整数
     * @return 累加和
     */
    public int sumGivenInt(int... ints) {
        int sum = 0;
        for (int i = 0; i < ints.length; i++) {
            sum += ints[i];
        }
        return sum;
    }

}
public class Main {

    public static void main(String[] args) {
        Calculator calculator = new Calculator();

        // [1, 100] 累加和: 5050
        System.out.println("[1, 100] 累加和: " + calculator.sumOne2Hundred());

        // [1, 1000] 累加和: 500500
        System.out.println("[1, 1000] 累加和: " + calculator.sumStart2End(1, 1000));

        // 任意多个整数累加: 979
        System.out.println("任意多个整数累加: " + calculator.sumGivenInt(66, 888, 25));
    }

}

Person 和 Calculator 两个类中一共定义了 4 个方法:
❄️ public void selfIntroduce()
❄️ public int sumOne2Hundred()
❄️ public int sumStart2End(int start, int end)
❄️ public int sumGivenInt(int... ints)
四个方法定义的最前面都有 public,它是访问修饰符(限制方法可以被访问的范围)。public 表示公共的,可访问范围最广。访问修饰符共有四个:① public、② protected、③ default、④ private
第一个方法(selfIntroduce)的 void 表示该方法没有返回值,而其他方法都有返回值(返回值类型是 int)
第一和第二个方法(selfIntroduce 和 sumOne2Hundred)都没有方法参数;sumStart2End 方法有2个方法参数,sumGivenInt 方法的方法参数是未知的(可能没有、可能1个、可能两个 …)

二、方法的调用机制

在前面的文章中博主分享过对象的内存布局和栈帧等概念,不知道的童鞋去看看吧,顺便支持一下博主:http://t.csdn.cn/moZa3
通过下面的代码分析方法的调用机制:

public class Person {

    /**
     * 计算两个整数的和
     */
    public int sumOfTwo(int n1, int n2) {
        return n1 + n2;
    }

}
public class Main {

    public static void main(String[] args) {
        Person person = new Person();

        // 520
        System.out.println(person.sumOfTwo(500, 20));
    }

}

9、Java 成员方法详解_第2张图片
9、Java 成员方法详解_第3张图片

三、成员方法的好处

提高代码的复用性(不用重复编写相同的代码)
将实现的细节封装起来,其他工程师调用方法即可,无需知道底层实现细节

成员方法提高代码复用性的代码体现:

打印下面的二维数组:
int[][] twoArray = {{5, 2, 0}, {6, 7, 8}, {1, 3, 9}};

public class MemberMethodAdvantage {

    public static void main(String[] args) {
        int[][] twoArray = {{5, 2, 0}, {6, 7, 8}, {1, 3, 9}};
        // 1. 打印 twoArray 数组
        System.out.print("\n");
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                System.out.print(" " + twoArray[i][j]);
            }
            System.out.println();
        }

        System.out.println();
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                System.out.print(" " + twoArray[i][j]);
            }
            System.out.println();
        }

        System.out.println();
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                System.out.print(" " + twoArray[i][j]);
            }
            System.out.println();
        }
    }

}

上面的代码,把打印二维数组的代码复制了三份,从而实现【打印二维数组】功能重复使用。但若是需要修改代码实现逻辑的话,则需要修改三处,这很不高效。
类的成员方法的实现逻辑被存放在 jvm 的方法区(且每个类的成员方法只在方法区保存一份),每个该类的对象都可调用方法区的成员方法,即使有一千个对象,成员方法也只有一个,真正是实现了代码的复用。

四、方法传参机制

看下面的代码,思考打印的值是什么?

public class ArgumentsPassingTest {

    public static void main(String[] args) {
        ArgumentsPassingTest passing = new ArgumentsPassingTest();
        int a = 66;
        int b = 88;
        passing.swap(a, b);
        // main の a = 66
        System.out.println("main の a = " + a);
        // main の b = 88
        System.out.println("main の b = " + b);
    }

    public void swap(int a, int b) {
        int temp = a; // temp = 66
        a = b; // a = 88
        b = temp; // b = 66
        // a = 88
        System.out.println("a = " + a);
        // b = 66
        System.out.println("b = " + b);
    }

}

基本数据类型传参是【值】传递
形参的任何改变不会影响实参

看下面的代码,思考打印的值是什么?

public class ArgumentsPassingTest {

    public static void main(String[] args) {
        int[] nums = new int[]{1, 2, 3};
        ArgumentsPassingTest test = new ArgumentsPassingTest();

        // call test 之前: nums = [1, 2, 3]
        System.out.println("call test 之前: nums = " + Arrays.toString(nums));
        test.arrTest(nums);
        // call test 之后: nums = [1, 5, 3]
        System.out.println("call test 之后: nums = " + Arrays.toString(nums));
    }

    private void arrTest(int[] nums) {
        nums[1] = nums[1] * 2 + 1;
    }

}

引用类型传参是引用(地址值)传递(通过地址值可以修改引用类型的值)

public class ArgumentsPassingTest {

    public static void main(String[] args) {
        ArgumentsPassingTest test = new ArgumentsPassingTest();

        Handsome handsome = new Handsome();
        // 1: 鹿晗
        System.out.println("1: " + handsome.name);

        test.handsomeTest2(handsome);
        // 2: 周杰伦
        System.out.println("2: " + handsome.name);

        test.handsomeTest1(handsome);
        // 3: 王俊凯
        System.out.println("3: " + handsome.name);

        test.handsomeTest3(handsome);
        // 4: 壹诺
        System.out.println("4: " + handsome.name);

        test.handsomeTest4(handsome);
        // 5: 潘忠举
        System.out.println("5: " + handsome.name);

        // Handsome.name = 潘忠举
        handsome.printName();

    }

    private void handsomeTest1(Handsome handsome1) {
        handsome1.name = "王俊凯";
    }

    private void handsomeTest2(Handsome handsome2) {
        handsome2.name = "周杰伦";
    }

    private void handsomeTest3(Handsome handsome3) {
        handsome3.name = "壹诺";
    }

    private void handsomeTest4(Handsome handsome3) {
        handsome3.name = "潘忠举";
    }

}

class Handsome {
    String name = "鹿晗";

    void printName() {
        System.out.println("Handsome.name = " + name);
    }
}

❄️ 引用类型传参的时候,形参的改变会影响实参
❄️ 方法返回值是引用类型,实际返回的是对象的地址值

public class ArgumentsPassingTest {

    public static void main(String[] args) {
        Flower flower = new Flower();
        flower.name = "兰花";
        flower.price = 61;

        // flower.name = 兰花
        System.out.println("flower.name = " + flower.name);
        // flower.price = 61
        System.out.println("flower.price = " + flower.price);

        Flower copyFlower = copyFlower(flower);
        // copyFlower.name = 兰花
        System.out.println("copyFlower.name = " + copyFlower.name);
        // copyFlower.price = 61
        System.out.println("copyFlower.price = " + copyFlower.price);

        // false【false 表示 flower 和 copyFlower 不是同一个对象】
        System.out.println(flower == copyFlower);
    }

    private static Flower copyFlower(Flower flower) {
        Flower flowerCopy = new Flower();
        flowerCopy.name = flower.name;
        flowerCopy.price = flower.price;
        return flowerCopy;
    }

}

class Flower {
    String name;
    int price;
}

好困啊,今天就写到这儿吧!

你可能感兴趣的:(Java,语言,java,开发语言,jvm)