day08复习
1. 方法的声明
- 方法声明的格式说明
测试类中方法的定义
*
* 0. 举例:
* Scanner类中:nextXxx():nextInt()
* Math类中:random() / sqrt()
* Arrays类中:equals() / toString() / sort(int[] arr) / binarySearch()
*
* 1. 方法的定义(或声明)格式:
* 权限修饰符 返回值类型 方法名(形参列表){
* //方法体
* }
* 补充:像 static \ final \ abstract \ native 等关键字修饰方法的情况,后续再讲
*
* 2. 定义的细节:
* ① 权限修饰符:修饰方法可以使用的权限修饰符有:public 、 protected 、缺省 、 private
* 关于权限修饰符我们放到封装性具体来讲。暂时修饰方法大家都使用public即可。
* ② 返回值类型:如果一个方法调用完以后,需要有相关数据的返回。那么我们就可以指定要返回的数据的类型。
* 方法可以分为:一类是有返回值的(需要指明返回值的类型。并且方法内需要使用return + 具体类型的变量或常量)
* 一类是没有返回值的(使用void表示返回值类型即可)。
*
* 开发中定义方法的话,到底要不要定义返回值类型呢?
* > 根据题目要求
* > 具体问题具体分析
* ③ 方法名:方法名是一个标识符,需要满足标识符定义的规则、规范。 “见名知意”
* ④ 形参列表:在形参的位置可以定义一个或多个变量。
* 格式:数据类型 变量1,数据类型 变量2,...
* 赋值:形参在方法被调用时,赋值。赋的值,通常称为实参。
*
* 开发中定义方法的话,到底要不要定义形参列表呢?
* > 根据题目要求
* > 具体问题具体分析
* ⑤ 方法体:声明在方法结构的一对{}内。当方法被调用时,真正执行的逻辑。
- 方法内的使用说明
① 方法内可以调用当前类的属性。执行方法时,属性的值即为调用当前方法的对象的属性值。
② 方法内可以调用当前类的(其他)方法。方法内不能定义方法
- return 关键字的使用
如果一个方法声明时,有返回值类型(即:返回值类型位置不是void),则方法内部一定要使用return结构。
格式 : return + 变量/常量。
return 的作用: ① 结束方法:在方法体内,一旦执行了return,则跳出当前方法。
② 结束方法的同时,可以返回一个变量或常量给方法的调用者。
- 代码示例
class User{
//1. 属性
String name;//名字
int age;//年龄
//2. 方法
public void eat(){
System.out.println("用户吃饭");
//eat();
// walk();
// System.out.println(show());
}
public void walk(){
System.out.println("用户走路");
}
public String show(){
return "name = " + name + ", age = " + age; //方法内可以调用当前类的属性
// return 123;
}
public void sleep(int hour){
System.out.println("每天睡眠" + hour + "个小时");
}
public double getAge(){
// return age;
return 1;
}
public void info(){
if(age >= 18){
System.out.println("成人了");
return; //用于表示方法的结束
}else{
System.out.println("未成年");
}
System.out.println("执行结束");
}
}
测试类:
public class UserTest {
public static void main(String[] args) {
// Scanner scan = new Scanner(System.in);
// int num = scan.nextInt();
User u1 = new User();
u1.name = "Tom";
u1.age = 10;
String info = u1.show();
System.out.println(info);
User u2 = new User();
u2.name = "Jerry";
System.out.println(u2.show());
System.out.println("############");
u1.eat();
}
}
2. 练习1
代码示例
package com.atguigu.exer;
/**
* @author shkstart
* @create 11:13
*/
public class Person {
String name;
int age = 10;
/**
* 表示性别。具体为:
* 0 : 女性
* 1 : 男性
*
*/
int sex;
//方法
public void study(){
System.out.println("studying");
}
public void showAge(){
//方法内可以调用当前类的属性
System.out.println("age = " + age);
}
/**
* 给对象增加年龄的方法
* @param i 要增加的年龄数
* @return 对象的年龄
*/
public int addAge(int i){//
age += i;
return age;
}
}
package com.atguigu.exer;
import java.util.Scanner;
/**
* 要求:
* (1)创建Person类的对象,设置该对象的name、age和sex属性,调用study方法,输出字符串“studying”,
* 调用showAge()方法显示age值,调用addAge()方法给对象的age属性值增加2岁。
* (2)创建第二个对象,执行上述操作,体会同一个类的不同对象之间的关系。
*
*
* @author shkstart
* @create 11:19
*/
public class PersonTest {//测试类
public static void main(String[] args) {
Person p1 = new Person();
p1.showAge();
//"对象.属性"
p1.name = "张政";
p1.age = 20;
p1.sex = 1;
p1.study();
p1.showAge();
int newAge = p1.addAge(2);
System.out.println(newAge);//22
System.out.println(p1.age);//22
System.out.println("#############");
Person p2 = new Person();
p2.showAge();//10
// p1.name.study();
//
// p1.name.toUpperCase();
}
}
- 内存解析
栈内存储:局部变量(方法内定义的变量、方法的形参)
堆空间:new 出来的数组、对象。(含成员变量)
成员变量有默认值
3. 练习2
利用面向对象的编程方法,设计类Circle计算圆的面积。
- 代码示例
package com.atguigu.exer1;
/**
*
* 2.利用面向对象的编程方法,设计类Circle计算圆的面积。
*
* @author shkstart
* @create 14:03
*/
public class Circle {
//属性
double radius;//半径
// double area;//面积
//方法
//错误的:
// public void findArea(double r){
// System.out.println(3.14 * r * r);
// }
//正确的方式一:
// public void findArea(){
// System.out.println(3.14 * radius * radius);
// }
//正确的方式二:
public double findArea(){
return 3.14 * radius * radius;
}
}
package com.atguigu.exer1;
/**
* @author shkstart
* @create 14:03
*/
public class CircleTest {
public static void main(String[] args) {
Circle c1 = new Circle();
c1.radius = 3.4;
// c1.findArea(4.5);
double area = c1.findArea();
System.out.println(area);
}
}
4. 对象数组
如果数组中的元素是类的对象,则称为对象数组。
比如:String[] \ Student[] \ Person[]
- 练习
定义类Student,包含三个属性:学号number(int),年级state(int),成绩score(int)。 创建20个学生对象,学号为1到20,年级和成绩都由随机数确定。
问题一:打印出3年级(state值为3)的学生信息。
问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
提示:
1) 生成随机数:Math.random(),返回值类型double;
2) 四舍五入取整:Math.round(double d),返回值类型long。
代码实现
/**
* 4. 对象数组题目:
* 定义类Student,包含三个属性:学号number(int),年级state(int),成绩score(int)。
*
* @author shkstart
* @create 14:14
*/
public class Student {
int number;//学号
int state;//年级
int score;//成绩
}
public class StudentTest {
public static void main(String[] args) {
//数组是引用数据类型,数组的元素可以是基本数据类型,也可以是引用数据类型:
//String[] arr = new String[10]
//int[][] arr1 = new int[10][];
//Student[] arr2 = new Student[10];
//创建对象数组
Student[] stus = new Student[20];
for(int i = 0;i < stus.length;i++){
//给数组元素赋值
stus[i] = new Student();
//给数组元素(对象)的属性赋值
stus[i].number = i + 1;
stus[i].state = (int)(Math.random() * 6 + 1);
stus[i].score = (int)(Math.random() * 101);
}
//问题一:打印出3年级(state值为3)的学生信息。
for(int i = 0;i <stus.length;i++){
if(3 == stus[i].state){
Student s = stus[i];
System.out.println("学生信息为:number = " + s.number + ", state = " + s.state + ", score = " + s.score);
}
}
//问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
//排序前:
System.out.println("排序前:");
for(int i = 0;i <stus.length;i++){
Student s = stus[i];
System.out.println("学生信息为:number = " + s.number + ", state = " + s.state + ", score = " + s.score);
}
//冒泡排序
for(int i = 0;i < stus.length - 1;i++){
for(int j = 0;j < stus.length - 1 -i;j++){
if(stus[j].score > stus[j + 1].score){
//错误的!
// int score = stus[j].score;
// stus[j].score = stus[j + 1].score;
// stus[j + 1].score = score;
//正确的:
Student temp = stus[j];
stus[j] = stus[j + 1];
stus[j + 1] = temp;
}
}
}
//排序后:
System.out.println("排序后:");
for(int i = 0;i <stus.length;i++){
Student s = stus[i];
System.out.println("学生信息为:number = " + s.number + ", state = " + s.state + ", score = " + s.score);
}
}
}
代码实现的升级
- Student
public class Student {
int number;//学号
int state;//年级
int score;//成绩
public String getInfo(){
return "学生信息为:number = " + number + ", state = " + state + ", score = " + score;
}
}
- StudentUtil
public class StudentUtil {
/**
* 打印出指定年级的学生信息
* @param stus 指定的学生数组
* @param state 指定的年级
*/
public void printStudentWithState(Student[] stus,int state){
for(int i = 0;i <stus.length;i++){
if(state == stus[i].state){
Student s = stus[i];
System.out.println(s.getInfo());
}
}
}
/**
* 遍历指定的学生数组中的学生信息
* @param stus
*/
public void printStudent(Student[] stus){
for(int i = 0;i <stus.length;i++){
Student s = stus[i];
System.out.println(s.getInfo());
}
}
/**
* 对学生数组进行排序
*/
public void sortStudents(Student[] stus,String sort){
if("ascend".equals(sort)){ //ascend:升序
for(int i = 0;i < stus.length - 1;i++){
for(int j = 0;j < stus.length - 1 -i;j++){
if(stus[j].score > stus[j + 1].score){
//正确的:
Student temp = stus[j];
stus[j] = stus[j + 1];
stus[j + 1] = temp;
}
}
}
}else if("descend".equals(sort)){ //descend:降序
for(int i = 0;i < stus.length - 1;i++){
for(int j = 0;j < stus.length - 1 -i;j++){
if(stus[j].score < stus[j + 1].score){
//正确的:
Student temp = stus[j];
stus[j] = stus[j + 1];
stus[j + 1] = temp;
}
}
}
}else{
System.out.println("指定的排序方式有误!");
}
}
}
- StudentTest
public class StudentTest { //测试类
public static void main(String[] args) {
//创建对象数组
Student[] stus = new Student[20];
for(int i = 0;i < stus.length;i++){
//给数组元素赋值
stus[i] = new Student();
//给数组元素(对象)的属性赋值
stus[i].number = i + 1;
stus[i].state = (int)(Math.random() * 6 + 1);
stus[i].score = (int)(Math.random() * 101);
}
//问题一:打印出3年级(state值为3)的学生信息。
StudentUtil util = new StudentUtil();
util.printStudentWithState(stus,3);
//问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息
//排序前:
System.out.println("排序前:");
util.printStudent(stus);
//冒泡排序
util.sortStudents(stus,"descend");
//排序后:
System.out.println("排序后:");
util.printStudent(stus);
}
}
思考问题
/**
* 自定义一个数组的工具类
*
* @author shkstart
* @create 14:49
*/
public class ArrayUtil {
//提供数值类型数组求最大值的方法
public int getMax(int[] arr){
int max = arr[0];
for(int i = 1;i < arr.length;i++){
if(max < arr[i]){
max = arr[i];
}
}
return max;
}
public double getMax(double[] arr){
//....
return 0.0;
}
//提供数值类型数组求最小值的方法
public int getMin(int[] arr){
int min = arr[0];
for(int i = 1;i < arr.length;i++){
if(min > arr[i]){
min = arr[i];
}
}
return min;
}
//提供数值类型数组求总和的方法
public int getSum(int[] arr){
int sum = 0;
for(int i = 0;i <arr.length;i++){
sum += arr[i];
}
return sum;
}
//提供数值类型数组求平均数的方法
public int getAvg(int[] arr){
return getSum(arr) / arr.length;
}
//数组的反转
public void reverse(int[] arr){
}
//数组的复制
public int[] copy(int[] arr){
return null;
}
//数组的遍历
public void printArray(int[] arr){
}
//数组的排序,默认从小到大
public void sort(int[] arr){
}
}
问题:填充上述ArrayUtil类中方法的方法体。填充完以后,可以如下方式使用:
public class ArrayUtilTest {
public static void main(String[] args) {
ArrayUtil util = new ArrayUtil();
int[] arr = new int[]{3,42,2,53,65,24,65,87,-95,-84,0,45};
int max = util.getMax(arr);
System.out.println(max);
}
}
5. 匿名对象
匿名对象: 创建的对象没有声明一个具体的变量名。
通常匿名对象只能使用一次。
- 代码演示
UserTest test = new UserTest();
User u3 = new User();
u3.name = "Tonny";
test.showUser(u3);
System.out.println(u3);
//匿名对象
new User().name = "Kitty";//对象1
new User().age = 10;//对象2
test.showUser(new User());//通常见到的匿名对象的使用场景
6. 方法的重载
/**
* 方法的重载(overload)
*
* 1. 概念:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
* 这样的多个方法,我们称彼此为方法的重载。
*
* 技巧:“两同一不同”:同一个类,相同的方法名;参数列表不同(参数个数不同 或参数类型不同)
*
* 2. 方法之间是否构成重载,与形参名、返回值类型、权限修饰符都没有关系
*
* 3. 如何确定调用某一个方法:① 通过方法名确定一波重载的方法 ② 通过赋的实参值,确定调用确定的形参对应的方法。
*
* 4. 同一个类中,相同方法名,形参列表也相同的方法,不允许存在多个。
*
* @author shkstart
* @create 15:28
*/
public class OverLoadTest {
public static void main(String[] args) {
OverLoadTest test = new OverLoadTest();
test.show(1.1);
test.show(1);
System.out.println(123);
System.out.println("hello");
}
//如下的4个方法构成重载
public void show(int i){
}
public void show(double d){
System.out.println("hello1");
}
public void show(String s,int i){
}
public void show(int i,String s){
}
//如下的3个方法与上述4个方法不构成重载
// public void show(double d1){
// System.out.println("hello2");
// }
// public double show(double d){
//
// return 0.0;
// }
// private void show(double d){}
}
说明:我们讲方法的重载的意义在于,大家需要清楚在一个类中不能定义相同方法名,相同形参列表的方法!因为编译器无法识别出两个方法的不同,导致调用时不能确定是哪个方法。
7. 可变个数形参的方法
package com.atguigu.java1;
/**
* jdk5.0新特性:可变个数形参的方法
* 1. 可变个数形参的格式:数据类型 ... 变量名
* 2. 我们在调用可变个数形参方法时,可以附的实参的个数有:0个,1个,2个,...多个
* 3. 将同一个类中,与可变个数形参的方法的方法相同名,但参数类型不同的方法之间,仍构成重载。(除了第4点)
* 4. 可变个数的形参 与 同类型的数组类型的形参相比,编译器认为是相同的参数类型,不构成重载。
* 5. 如果一个方法有可变个数的形参,则此可变个数的形参必须声明在方法形参的最后。
* 6. 一个方法中最多声明一个可变个数的形参。
*
* @author shkstart
* @create 16:08
*/
public class ArgsTest {
public static void main(String[] args) {
ArgsTest test = new ArgsTest();
test.show(123);
test.show(new int[]{123,234});
test.show(123,234);
test.show();
}
//如下的4个方法构成重载
public void show(int i){
System.out.println("11111");
}
public void show(double d){
System.out.println("22222");
}
public void show(String s,int i){
System.out.println("33333");
}
//String sql = "select id ,name,email from table_user where id > ? and email like ? ;
public void show(int ... args){
System.out.println("44444");
for(int i = 0;i < args.length;i++){
System.out.println(args[i]);
}
}
public void show(String s,int ... args){
}
// public void show(int[] args){
// for(int i = 0;i < args.length;i++){
// System.out.println(args[i]);
// }
// }
}
8. 补充练习
-
练习1
-
练习2
-
练习3