##################################################
目录
##################################################
——————————
没错 数组也能作为参数
应该早就想到了啊。。 变量可以 数组自然也行
想想 还有什么类似的吗?。。没错对象……绝望吧!
- 这样做有一个好处 不仅不用敲一大串来声明数组 还不用指定长度!!
- 自由的数组才是最理想的数组!
定义语法:
- 访问修饰符 返回值类型 方法名 ( 数据类型 数组名[] ) {
-
- /* 方法体 */
- }
调用语法:
- 类名 对象名 = new 类名();
- 对象名.方法名 ( 数组名 );
——————————
我们将多个类型相同的数值型数据储存在数组中
然后对其求 总和、平均值、最大值、最小值 等操作是实际应用中最常见的操作
我们可以设计求 总和、平均值、最大值、最小值 等的方法
并把数组作为参数 这就能在多种场合下调用这些方法 并且得到结果
需求:
请输入 10 个学生的成绩
输出平均成绩和最高成绩
Main.java code:
- import java.util.Scanner;
-
- /**
- * 主类
- */
- public class Main {
-
- /**
- * 程序入口方法
- * 功能:程序从这里开始
- */
- public static void main(String[] args) {
-
- // 初始化相应对象
- Scanner sc = new Scanner(System.in);
- Student st = new Student();
-
- // 循环录入成绩
- System.out.print ( "请输入 10 名学生的成绩 <<< " );
- for ( int i = 0; i < st.scores.length; i ++ )
- st.scores[i] = sc.nextInt();
-
- // 输出平均成绩 st.calAvg 的参数是一个数组
- System.out.println ( "平均成绩为 >>> " + st.calAvg ( st.scores ) );
-
- // 输出最高成绩
- System.out.println ( "最高成绩为 >>> " + st.calMax ( st.scores ) );
- }
- }
-
- /**
- * 学生类
- */
- class Student {
-
- /** 成绩数组 */
- int scores[] = new int[10];
-
- /** 最高成绩 */
- int max;
-
- /** 平均成绩 */
- double avg;
-
- /**
- * 求平均成绩方法
- * 功能:接收指定 量、类型 的数组 计算并返回平均值
- */
- public double calAvg(int[] array) {
-
- // 求和
- int sum = 0;
- for ( int i = 0; i < array.length; i ++ )
- sum += array[i];
-
- // 计算平均值 总分除以数组长度!
- double avg = (double)(sum / array.length);
-
- // 返回平均值
- return avg;
- }
-
- /**
- * 求最高成绩方法
- * 功能:接收接收指定 量、类型 的数组 比较并返回最高值
- */
- public int calMax(int[] array) {
-
- // 初始化最大值 假设第一个元素为最大
- int max = array[0];
-
- // 比较处理后得到最大值
- for ( int i = 0; i < array.length; i ++ ) {
-
- if (max < array[i])
- max = array[i];
- }
-
- // 返回最大值
- return max;
- }
- }
Bash demo:
- [lilian@CentOS javaTest]$ javac Main.java
- [lilian@CentOS javaTest]$ java Main
- 请输入 10 名学生的成绩 <<< 10 10 10 10 10 10 10 10 10 10
- 平均成绩为 >>> 10.0
- 最高成绩为 >>> 10
- [lilian@CentOS javaTest]$ java Main
- 请输入 10 名学生的成绩 <<< 10 20 30 40 50 60 70 80 90 100
- 平均成绩为 >>> 55.0
- 最高成绩为 >>> 100
- [lilian@CentOS javaTest]$
都是带数组参数并且带返回值的方法
另外 可能发现了 我多声明了一个 array 数组
scores 数组是成员属性 完全可以使用 scores 数组 我却使用了 array 数组
这样做只是为了证明 这样声明的数组 很方便!
虽然定义方法时没有指定数组大小 but 在调用方法时确定传递的数组大小
##################################################
——————————
没错 对象也能作为参数
应该早就想到了啊。。 变量可以 数组也行 对象也可以啊!!
数组作为参数很好理解
而对象作为参数就会让你变成一只小萌比~~~…
来先看一个需求:
还记得我们之前增加姓名的例子吗
这里我们假设先完成了一个增加学生姓名的项目
如果不仅要增加学生的姓名 还要增加学生的年龄和成绩 怎么办呢?
- 我们可以先来思考一个用数组作为参数的笨方法
-
- 例如 设计一个方法 通过传递一个姓名参数来实现增加姓名功能
- 然后再分别设计两个方法 功能分别是增加 年龄、成绩 参数都是数组
-
- 这样做有一个问题 即 在类中声明的数组过多、在方法中传递的参数过多!
-
- 什么?这还不算是问题?
- 那 如果我们想增加更多的信息呢?
- 家庭住址、联系电话、身高、体重、性别。。。。。。
-
- 如果条件多达一百个 还要一个个定义吗?一千个呢!
- 定义那么多的数组和参数 真的是最好的解决方案吗?
-
- 好,你意识到了问题的严重性 现在我们使用面向对象的思想解决这个需求!
所以我们可以使用面向对象的思想来解决问题
那就是 把所有要增加的信息封装到学生类中
只需要在方法中传递一个学生对象即可包含所有的信息!
——————————
%%%%%
Main.java 代码:
- import java.util.Scanner;
-
- /**
- * 主要类
- */
- public class Main {
-
- /**
- * 程序入口方法
- * 功能:程序从这里开始
- */
- public static void main(String[] args) {
-
- // 实例化输入对象
- Scanner sc = new Scanner(System.in);
-
- // 实例化第一个学生对象 st_1 并初始化这个学生的信息
- Student st_1 = new Student(); /* 实例化 st_1 学生对象 对象类型为 Student 学生类型 */
- System.out.print ( "\n请输入学生编号 <<< " );
- st_1.id = sc.nextInt(); /* 为 st_1 这个学生赋值学生编号 */
- System.out.print ( "请输入学生姓名 <<< " );
- st_1.name = sc.next(); /* 为 st_1 这个学生赋值学生姓名 */
- System.out.print ("请输入学生年龄 <<< " );
- st_1.age = sc.nextInt(); /* 为 st_1 这个学生赋值学生年龄 */
- System.out.print ( "请输入学生成绩 <<< " );
- st_1.score = sc.nextInt(); /* 为 st_1 这个学生赋值学生成绩 */
-
- // 创建第二个学生 st_2 并且输入第二个学生的一系列信息
- Student st_2 = new Student();
- System.out.print ( "\n请输入学生编号 <<< " );
- st_2.id = sc.nextInt();
- System.out.print ( "请输入学生姓名 <<< " );
- st_2.name = sc.next();
- System.out.print ( "请输入学生年龄 <<< " );
- st_2.age = sc.nextInt();
- System.out.print ( "请输入学生成绩 <<< " );
- st_2.score = sc.nextInt();
-
- // 创建一个老师对象 类型为 StudentBiz 学生管理类型
- StudentBiz St = new StudentBiz();
- St.add(st_1); /* 新增学生对象 */
- St.add(st_2); /* 存储第二个学生的一系列信息 */
-
- // 显示学生对象
- System.out.println();
- St.show(); /* 调用老师让老师输出所有学生的信息 */
- }
- }
-
- /**
- * 学生类
- * 这里可以发现 声明类名我没有用 public 修饰符控制访问权限 但是起到同样的效果 自动换成默认权限
- */
- class Student {
-
- /**
- * 一系列成员属性变量
- * 权限:公开的
- * id = 学生号
- * name = 名字
- * age = 年龄
- * score = 成绩
- */
- public int id;
- public String name;
- public int age;
- public int score;
-
-
- /**
- * 显示信息方法
- * 格式:学生卡号 学生姓名 学生年龄 学生成绩
- */
- public void show() {
-
- System.out.println ( id + "\t" + name + "\t" + age + "\t" + score );
- }
- }
-
- /**
- * 学生管理类
- */
- class StudentBiz {
-
- /** 学生数组 */
- Student st[] = new Student[100]; /* 就是这个对象数组 用来存储一个个带着一系列信息的学生对象 */
-
- /**
- * 增加学生方法
- * @param 一个学生
- */
- public void add(Student stu) {
-
- for ( int i = 0; i < st.length; i ++ ) {
-
- if (st[i] == null) {
-
- st[i] = stu;
- break;
- }
- }
- }
-
- /**
- * 显示本班学生信息方法
- * @param 显示信息
- */
- public void show() {
-
- System.out.println ( "@@本班学生列表@@" );
-
- for ( int i = 0; i < st.length; i ++ ) {
- /* 这里很有意思哦 就是挨个调用我们储存的一个个学生对象 然后挨个调用里面的 show() 方法 */
-
- if (st[i] != null)
- st[i].show();
- }
-
- System.out.println();
- }
- }
Bash 测试:
- [lilian@CentOS javaTest]$ javac Main.java
- [lilian@CentOS javaTest]$ java Main
-
- 请输入学生编号 <<< 36
- 请输入学生姓名 <<< 老姐姐
- 请输入学生年龄 <<< 45
- 请输入学生成绩 <<< 108
- 请输入学生编号 <<< 37
- 请输入学生姓名 <<< 小老弟
- 请输入学生年龄 <<< 3
- 请输入学生成绩 <<< 360
- @@本班学生列表@@
- 36 老姐姐 45 108
- 37 小老弟 3 360
-
- [lilian@CentOS javaTest]$
有没有感觉到震撼呢?
%%%%%
封装成员变量的时候 会用到访问修饰符 public
还记得访问修饰符是怎么用的吗?
就是控制谁能访问被修饰的资源!
声明一个权限公开访问的类:
访问修饰符 关键字 类名 { }
声明一个权限公开访问的方法:
访问修饰符 返回值类型 方法名 ( 参数列表 ) { }
那么自然可以声明一个权限公开访问的 成员变量/成员属性
就是说 权限是公开的 谁都可以访问调用:
访问修饰符 数据类型 变量名;
访问修饰符也是一门学问 就像字符串这里先不深入 点到即可
示例声明公开成员属性:
- class Student {
-
- /* 公开的成员属性 */
- public int id;
- public String name;
- public int age;
- public int score;
-
- public void show() {
-
- System.out.println ( id + "\t" + name + "\t" +age + "\t" + score );
- }
- }
%%%%%
另外 这里我们再教一个有意思的初始化对象方法
来看这段:
类名[] 对象名 = new 类名[储存的对象个数];
什么意思呢?
就是说 声明了一个大小确定的对象数组
没错 就是对象数组 一共可以储存你指定的个数个对象
而不是 int 型数组、double型数组、char 数组、String 数组
这是对象数组 类型就是她所属的类
储存的值也不是 整数型、小数型、字符型、字符串型
而是一个个对象
例如对象数组:
Student st[] = new Student[100];
就是说 声明了一个类型为 Student 的对象数组
名字叫 st 长度为 100 就是说 这个 st 对象数组一共能储存 100 个对象
又是对象参数又是对象数组的,会不会已经晕了……
对象数组储存的不是 整形、小数型、字符型、字符串型 而是 相应类的类型 的 对象们
%%%%%
调用的时候 接收方和传送方都要怎么定义呢?
接收方声明定义的对象参数方法:
- 访问修饰符 返回值类型 方法名 ( 对象所属类/对象类型 名字 ) {
-
- /* 方法体 */
- }
还记得吗 我们讲过 对象的类型 就是她所属的那个类
对象是类的实例 类是对象的类型 现在总能理解了吧?
这里我就不列举变量那一套概念了 自己脑补!
当然 接收的值 是一个对象!!
记住了 实参是一个对象
然后在这个方法内使用我们定义的标识符来调用接收的值
示例声明定义对象方法:
- public void add ( Student stu ) {
- /* stu 临时接收储存对象值 然后方法体拿来处理
- *
- * 这段代码呢 stu 这个对象的类型/这个 “变量” 的类型 暂且这么理解
- * 她的类型是 Student 学生类 就是储存类型为学生类的对象
- * 值是一个学生对象 类型就是 Student 学生类
- *
- * 最后在这个方法中 我们想要接收外面的值 只需要调用 stu 这个标识符就好
- *
- * 然后就是对这个对象值的处理了
- * 就是把 stu 这个接收的外面的对象值 放进相应的 st 数组
- * st 数组我们定义的是最多能存放 100 个对象
- */
-
- for ( int i = 0; i < st.length; i ++ ) {
-
- if (st[i] == null) {
-
- st[i] = stu;
- break;
- }
- }
- }
传送方的调用传参就简单了 传送一个对象过来就好
跟以前的传参一样 只不过参数换成了对象
调用传参语法:
对象名.方法名(需要储存的对象);
示例代码:
- StudentBiz St = new StudentBiz();
- St.add(st_1);
传送 st_1 这个对象值 给类型为 StudentBiz 类 的 St 对象的 add 方法/行为
然后。。没然后了 然后就是 add() 自己处理的事咯。。
%%%%%
最后说说这个储存的对象吧
一开始就说了
那就是 把所有要增加的信息封装到一个类中
然后只需要在方法中传递一个此类对象即可包含所有要增加的信息!
先来看看初始化和赋值
- Student st_1 = new Student();
-
- System.out.print ( "\n请输入学生编号 <<< " );
- st_1.id = sc.nextInt();
-
- System.out.print ( "请输入学生姓名 <<< " );
- st_1.name = sc.next();
-
- System.out.print ( "请输入学生年龄 <<< " );
- st_1.age = sc.nextInt();
-
- System.out.print ( "请输入学生成绩 <<< " );
- st_1.score = sc.nextInt();
好现在 Student 学生类型的 st_1 这个学生对象 的四个 成员属性/新增信息 都有值了
%%%%%
然后考虑一下 将现在这个对象所包含的值 一起储存在哪里?
当然是对象数组 就像储存 整型、小数型、字符型、字符串型 的数组
我们将 对象和她包含的信息 储存在对象数组内!
示例代码:
- StudentBiz St = new StudentBiz();
- St.add(st_1);
将 st_1 这个对象和她包含的值传送给 StudentBiz 类型的 St 对象的 add 方法/功能
如果你是个狠人 跟着我一路看到这里 恭喜你神功修炼小成!可以解决绝绝绝大多数的问题了!!!
##################################################
——————————
- 值传递
- 就是在方法调用的时候
- 实参是将自己的一份拷贝赋给形参
- 在方法内对该参数值的修改不影响原来的实参
-
- 引用传递
- 是在方法调用的时候
- 实参将自己的地址传递给形参
- 此时方法内对该参数值的改变就是对该实参的实际操作
——————————
基本类型都是值传递
引用类型都是地址值传递
基本类型传递的是值的拷贝
也就是说传递后就互不相关了
不管这个值以后在方法中如何变化 源头永远不会被影响
引用类型传递的是引用地址值 引用有可能会被影响
如果是对象的话,就是将引用的值复制一份给方法当参数
如果是根据引用把堆里的对象修改了,那么对象就真被修改了!
不过不是被创建赋值给的那个引用修改的 而是方法里的一个复制的引用副本给修改的
而 String 字符串类型具有不可变性质 是特殊的引用类型
String 类型其作用跟基本类型一样 传递后不相关