• 8.2_[Java 方法]-深入带参 数组/对象 作为参数的方法以及 值传递/引用传递 的区别


    ##################################################

    目录

    数组作为参数的方法

    定义数组参数的方法与调用

    数组参数方法的示例程序

    对象作为参数的方法

    当数组太多而数组参数不切实际就需要对象参数这种东西

    分段解释对象作为数组方法的程序代码

    先运行研究一下演示代码再看后面的分段解释

    声明公开成员属性

    声明对象数组

    声明定义调用对象参数方法

    初始化单个对象的值

    将单个对象存储进对象数组达到暂时保存的目的

    值传递跟引用传递

    值传递跟引用传递有什么区别

    基本类型与引用类型


    ##################################################

    数组作为参数的方法

    ——————————

    定义数组参数的方法与调用

            没错 数组也能作为参数
            应该早就想到了啊。。 变量可以 数组自然也行
            想想 还有什么类似的吗?。。没错对象……绝望吧!

    1.         这样做有一个好处 不仅不用敲一大串来声明数组 还不用指定长度!!
    2.         自由的数组才是最理想的数组!

            定义语法:

    1. 访问修饰符 返回值类型 方法名 ( 数据类型 数组名[] ) {
    2. /* 方法体 */
    3. }

            调用语法:

    1. 类名 对象名 = new 类名();
    2. 对象名.方法名 ( 数组名 );

    ——————————

    数组参数方法的示例程序

            我们将多个类型相同的数值型数据储存在数组中
            然后对其求 总和、平均值、最大值、最小值 等操作是实际应用中最常见的操作
            我们可以设计求 总和、平均值、最大值、最小值 等的方法
            并把数组作为参数 这就能在多种场合下调用这些方法 并且得到结果

            需求:

    请输入 10 个学生的成绩
    输出平均成绩和最高成绩

            Main.java code:

    1. import java.util.Scanner;
    2. /**
    3. * 主类
    4. */
    5. public class Main {
    6. /**
    7. * 程序入口方法
    8. * 功能:程序从这里开始
    9. */
    10. public static void main(String[] args) {
    11. // 初始化相应对象
    12. Scanner sc = new Scanner(System.in);
    13. Student st = new Student();
    14. // 循环录入成绩
    15. System.out.print ( "请输入 10 名学生的成绩 <<< " );
    16. for ( int i = 0; i < st.scores.length; i ++ )
    17. st.scores[i] = sc.nextInt();
    18. // 输出平均成绩 st.calAvg 的参数是一个数组
    19. System.out.println ( "平均成绩为 >>> " + st.calAvg ( st.scores ) );
    20. // 输出最高成绩
    21. System.out.println ( "最高成绩为 >>> " + st.calMax ( st.scores ) );
    22. }
    23. }
    24. /**
    25. * 学生类
    26. */
    27. class Student {
    28. /** 成绩数组 */
    29. int scores[] = new int[10];
    30. /** 最高成绩 */
    31. int max;
    32. /** 平均成绩 */
    33. double avg;
    34. /**
    35. * 求平均成绩方法
    36. * 功能:接收指定 量、类型 的数组 计算并返回平均值
    37. */
    38. public double calAvg(int[] array) {
    39. // 求和
    40. int sum = 0;
    41. for ( int i = 0; i < array.length; i ++ )
    42. sum += array[i];
    43. // 计算平均值 总分除以数组长度!
    44. double avg = (double)(sum / array.length);
    45. // 返回平均值
    46. return avg;
    47. }
    48. /**
    49. * 求最高成绩方法
    50. * 功能:接收接收指定 量、类型 的数组 比较并返回最高值
    51. */
    52. public int calMax(int[] array) {
    53. // 初始化最大值 假设第一个元素为最大
    54. int max = array[0];
    55. // 比较处理后得到最大值
    56. for ( int i = 0; i < array.length; i ++ ) {
    57. if (max < array[i])
    58. max = array[i];
    59. }
    60. // 返回最大值
    61. return max;
    62. }
    63. }

            Bash demo:

    1. [lilian@CentOS javaTest]$ javac Main.java
    2. [lilian@CentOS javaTest]$ java Main
    3. 请输入 10 名学生的成绩 <<< 10 10 10 10 10 10 10 10 10 10
    4. 平均成绩为 >>> 10.0
    5. 最高成绩为 >>> 10
    6. [lilian@CentOS javaTest]$ java Main
    7. 请输入 10 名学生的成绩 <<< 10 20 30 40 50 60 70 80 90 100
    8. 平均成绩为 >>> 55.0
    9. 最高成绩为 >>> 100
    10. [lilian@CentOS javaTest]$

            都是带数组参数并且带返回值的方法

            另外 可能发现了 我多声明了一个 array 数组
            scores 数组是成员属性 完全可以使用 scores 数组 我却使用了 array 数组
            这样做只是为了证明 这样声明的数组 很方便!

            虽然定义方法时没有指定数组大小 but 在调用方法时确定传递的数组大小

    ##################################################

    对象作为参数的方法

    ——————————

    当数组太多而数组参数不切实际就需要对象参数这种东西

            没错 对象也能作为参数
            应该早就想到了啊。。 变量可以 数组也行 对象也可以啊!!

            数组作为参数很好理解
            而对象作为参数就会让你变成一只小萌比~~~…
     

            来先看一个需求:

    还记得我们之前增加姓名的例子吗
    这里我们假设先完成了一个增加学生姓名的项目
    如果不仅要增加学生的姓名 还要增加学生的年龄和成绩 怎么办呢?

    1. 我们可以先来思考一个用数组作为参数的笨方法
    2. 例如 设计一个方法 通过传递一个姓名参数来实现增加姓名功能
    3. 然后再分别设计两个方法 功能分别是增加 年龄、成绩 参数都是数组
    4. 这样做有一个问题 即 在类中声明的数组过多、在方法中传递的参数过多!
    5. 什么?这还不算是问题?
    6. 那 如果我们想增加更多的信息呢?
    7. 家庭住址、联系电话、身高、体重、性别。。。。。。
    8. 如果条件多达一百个 还要一个个定义吗?一千个呢!
    9. 定义那么多的数组和参数 真的是最好的解决方案吗?
    10. 好,你意识到了问题的严重性 现在我们使用面向对象的思想解决这个需求!

            所以我们可以使用面向对象的思想来解决问题

    那就是 把所有要增加的信息封装到学生类中
    只需要在方法中传递一个学生对象即可包含所有的信息!

    ——————————

    分段解释对象作为数组方法的程序代码

    %%%%%

    先运行研究一下演示代码再看后面的分段解释

            Main.java 代码:

    1. import java.util.Scanner;
    2. /**
    3. * 主要类
    4. */
    5. public class Main {
    6. /**
    7. * 程序入口方法
    8. * 功能:程序从这里开始
    9. */
    10. public static void main(String[] args) {
    11. // 实例化输入对象
    12. Scanner sc = new Scanner(System.in);
    13. // 实例化第一个学生对象 st_1 并初始化这个学生的信息
    14. Student st_1 = new Student(); /* 实例化 st_1 学生对象 对象类型为 Student 学生类型 */
    15. System.out.print ( "\n请输入学生编号 <<< " );
    16. st_1.id = sc.nextInt(); /* 为 st_1 这个学生赋值学生编号 */
    17. System.out.print ( "请输入学生姓名 <<< " );
    18. st_1.name = sc.next(); /* 为 st_1 这个学生赋值学生姓名 */
    19. System.out.print ("请输入学生年龄 <<< " );
    20. st_1.age = sc.nextInt(); /* 为 st_1 这个学生赋值学生年龄 */
    21. System.out.print ( "请输入学生成绩 <<< " );
    22. st_1.score = sc.nextInt(); /* 为 st_1 这个学生赋值学生成绩 */
    23. // 创建第二个学生 st_2 并且输入第二个学生的一系列信息
    24. Student st_2 = new Student();
    25. System.out.print ( "\n请输入学生编号 <<< " );
    26. st_2.id = sc.nextInt();
    27. System.out.print ( "请输入学生姓名 <<< " );
    28. st_2.name = sc.next();
    29. System.out.print ( "请输入学生年龄 <<< " );
    30. st_2.age = sc.nextInt();
    31. System.out.print ( "请输入学生成绩 <<< " );
    32. st_2.score = sc.nextInt();
    33. // 创建一个老师对象 类型为 StudentBiz 学生管理类型
    34. StudentBiz St = new StudentBiz();
    35. St.add(st_1); /* 新增学生对象 */
    36. St.add(st_2); /* 存储第二个学生的一系列信息 */
    37. // 显示学生对象
    38. System.out.println();
    39. St.show(); /* 调用老师让老师输出所有学生的信息 */
    40. }
    41. }
    42. /**
    43. * 学生类
    44. * 这里可以发现 声明类名我没有用 public 修饰符控制访问权限 但是起到同样的效果 自动换成默认权限
    45. */
    46. class Student {
    47. /**
    48. * 一系列成员属性变量
    49. * 权限:公开的
    50. * id = 学生号
    51. * name = 名字
    52. * age = 年龄
    53. * score = 成绩
    54. */
    55. public int id;
    56. public String name;
    57. public int age;
    58. public int score;
    59. /**
    60. * 显示信息方法
    61. * 格式:学生卡号 学生姓名 学生年龄 学生成绩
    62. */
    63. public void show() {
    64. System.out.println ( id + "\t" + name + "\t" + age + "\t" + score );
    65. }
    66. }
    67. /**
    68. * 学生管理类
    69. */
    70. class StudentBiz {
    71. /** 学生数组 */
    72. Student st[] = new Student[100]; /* 就是这个对象数组 用来存储一个个带着一系列信息的学生对象 */
    73. /**
    74. * 增加学生方法
    75. * @param 一个学生
    76. */
    77. public void add(Student stu) {
    78. for ( int i = 0; i < st.length; i ++ ) {
    79. if (st[i] == null) {
    80. st[i] = stu;
    81. break;
    82. }
    83. }
    84. }
    85. /**
    86. * 显示本班学生信息方法
    87. * @param 显示信息
    88. */
    89. public void show() {
    90. System.out.println ( "@@本班学生列表@@" );
    91. for ( int i = 0; i < st.length; i ++ ) {
    92. /* 这里很有意思哦 就是挨个调用我们储存的一个个学生对象 然后挨个调用里面的 show() 方法 */
    93. if (st[i] != null)
    94. st[i].show();
    95. }
    96. System.out.println();
    97. }
    98. }

            Bash 测试:

    1. [lilian@CentOS javaTest]$ javac Main.java
    2. [lilian@CentOS javaTest]$ java Main
    3. 请输入学生编号 <<< 36
    4. 请输入学生姓名 <<< 老姐姐
    5. 请输入学生年龄 <<< 45
    6. 请输入学生成绩 <<< 108
    7. 请输入学生编号 <<< 37
    8. 请输入学生姓名 <<< 小老弟
    9. 请输入学生年龄 <<< 3
    10. 请输入学生成绩 <<< 360
    11. @@本班学生列表@@
    12. 36 老姐姐 45 108
    13. 37 小老弟 3 360
    14. [lilian@CentOS javaTest]$

            有没有感觉到震撼呢?

    %%%%%

    声明公开成员属性

            封装成员变量的时候 会用到访问修饰符 public
            还记得访问修饰符是怎么用的吗?

    就是控制谁能访问被修饰的资源!

            声明一个权限公开访问的类:

    访问修饰符 关键字 类名 { }

            声明一个权限公开访问的方法:

    访问修饰符 返回值类型 方法名 ( 参数列表 ) { }

            那么自然可以声明一个权限公开访问的 成员变量/成员属性
            就是说 权限是公开的 谁都可以访问调用:

    访问修饰符 数据类型 变量名;

            访问修饰符也是一门学问 就像字符串这里先不深入 点到即可

            示例声明公开成员属性:

    1. class Student {
    2. /* 公开的成员属性 */
    3. public int id;
    4. public String name;
    5. public int age;
    6. public int score;
    7. public void show() {
    8. System.out.println ( id + "\t" + name + "\t" +age + "\t" + score );
    9. }
    10. }

    %%%%%

    声明对象数组

            另外 这里我们再教一个有意思的初始化对象方法
            来看这段:

    类名[] 对象名 = new 类名[储存的对象个数];

            什么意思呢?
            就是说 声明了一个大小确定的对象数组
            没错 就是对象数组 一共可以储存你指定的个数个对象

            而不是 int  型数组、double型数组、char 数组、String 数组
            这是对象数组 类型就是她所属的类
            储存的值也不是 整数型、小数型、字符型、字符串型
            而是一个个对象

            例如对象数组:

    Student st[] = new Student[100];

            就是说 声明了一个类型为 Student 的对象数组
            名字叫 st 长度为 100 就是说 这个 st 对象数组一共能储存 100 个对象
     

            又是对象参数又是对象数组的,会不会已经晕了……

    对象数组储存的不是 整形、小数型、字符型、字符串型 而是 相应类的类型 的 对象们

    %%%%%

    声明定义调用对象参数方法

            调用的时候 接收方和传送方都要怎么定义呢?

            接收方声明定义的对象参数方法:

    1. 访问修饰符 返回值类型 方法名 ( 对象所属类/对象类型 名字 ) {
    2. /* 方法体 */
    3. }

            还记得吗 我们讲过 对象的类型 就是她所属的那个类
            对象是类的实例 类是对象的类型 现在总能理解了吧?
            这里我就不列举变量那一套概念了 自己脑补!

            当然 接收的值 是一个对象!!
            记住了 实参是一个对象
            然后在这个方法内使用我们定义的标识符来调用接收的值

            示例声明定义对象方法:

    1. public void add ( Student stu ) {
    2. /* stu 临时接收储存对象值 然后方法体拿来处理
    3. *
    4. * 这段代码呢 stu 这个对象的类型/这个 “变量” 的类型 暂且这么理解
    5. * 她的类型是 Student 学生类 就是储存类型为学生类的对象
    6. * 值是一个学生对象 类型就是 Student 学生类
    7. *
    8. * 最后在这个方法中 我们想要接收外面的值 只需要调用 stu 这个标识符就好
    9. *
    10. * 然后就是对这个对象值的处理了
    11. * 就是把 stu 这个接收的外面的对象值 放进相应的 st 数组
    12. * st 数组我们定义的是最多能存放 100 个对象
    13. */
    14. for ( int i = 0; i < st.length; i ++ ) {
    15. if (st[i] == null) {
    16. st[i] = stu;
    17. break;
    18. }
    19. }
    20. }

            传送方的调用传参就简单了 传送一个对象过来就好
            跟以前的传参一样 只不过参数换成了对象

            调用传参语法:

    对象名.方法名(需要储存的对象);

            示例代码:

    1. StudentBiz St = new StudentBiz();
    2. St.add(st_1);

            传送 st_1 这个对象值 给类型为 StudentBiz 类 的 St 对象的 add 方法/行为
            然后。。没然后了 然后就是 add() 自己处理的事咯。。

    %%%%%

    初始化单个对象的值

            最后说说这个储存的对象吧

            一开始就说了
            那就是 把所有要增加的信息封装到一个类中
            然后只需要在方法中传递一个此类对象即可包含所有要增加的信息!

            先来看看初始化和赋值

    1. Student st_1 = new Student();
    2. System.out.print ( "\n请输入学生编号 <<< " );
    3. st_1.id = sc.nextInt();
    4. System.out.print ( "请输入学生姓名 <<< " );
    5. st_1.name = sc.next();
    6. System.out.print ( "请输入学生年龄 <<< " );
    7. st_1.age = sc.nextInt();
    8. System.out.print ( "请输入学生成绩 <<< " );
    9. st_1.score = sc.nextInt();

            好现在 Student 学生类型的 st_1 这个学生对象 的四个 成员属性/新增信息 都有值了

    %%%%%

    将单个对象存储进对象数组达到暂时保存的目的

            然后考虑一下 将现在这个对象所包含的值 一起储存在哪里?
            当然是对象数组 就像储存 整型、小数型、字符型、字符串型 的数组

            我们将 对象和她包含的信息 储存在对象数组内!

            示例代码:

    1. StudentBiz St = new StudentBiz();
    2. St.add(st_1);

            将 st_1 这个对象和她包含的值传送给 StudentBiz 类型的 St 对象的 add 方法/功能

    如果你是个狠人 跟着我一路看到这里 恭喜你神功修炼小成!可以解决绝绝绝大多数的问题了!!!

    ##################################################

    值传递跟引用传递

    ——————————

    值传递跟引用传递有什么区别

    1.         值传递
    2. 就是在方法调用的时候
    3. 实参是将自己的一份拷贝赋给形参
    4. 在方法内对该参数值的修改不影响原来的实参
    5.         引用传递
    6. 是在方法调用的时候
    7. 实参将自己的地址传递给形参
    8. 此时方法内对该参数值的改变就是对该实参的实际操作

    ——————————

    基本类型与引用类型

            基本类型都是值传递

            引用类型都是地址值传递

            基本类型传递的是值的拷贝

    也就是说传递后就互不相关了

    不管这个值以后在方法中如何变化 源头永远不会被影响

            引用类型传递的是引用地址值 引用有可能会被影响

    如果是对象的话,就是将引用的值复制一份给方法当参数

    如果是根据引用把堆里的对象修改了,那么对象就真被修改了!

    不过不是被创建赋值给的那个引用修改的 而是方法里的一个复制的引用副本给修改的

    而 String 字符串类型具有不可变性质 是特殊的引用类型

    String 类型其作用跟基本类型一样 传递后不相关

  • 相关阅读:
    设备树添加版本信息
    原型和原型链
    这才是Git的正确学习方式
    洛谷 P7174 [COCI2014-2015#4] CESTA
    商业智能BI如何帮助企业
    vue.js中slot插槽的作用
    10月TIOBE榜Java跌出前三!要不我转回C#吧
    初探富文本之React实时预览
    【从零开始的Java开发】2-10-4 Servlet与jsp进阶:请求与响应的结构、请求转发与响应重定向、Cookie
    go语言面试
  • 原文地址:https://blog.csdn.net/m0_67268286/article/details/124966749