第五章 面向对象基础---上(参数问题、方法的重载、方法的递归调用、对象数组)

1.特殊参数之一:可变参数

        在JDK1.5之后,当定义一个方法时,形参的类型可以确定,但是形参的个数不确定,那么可以考虑使用可变参数。可变参数的格式:

【修饰符】 返回值类型 方法名(【非可变参数部分的形参列表,】参数类型... 形参名){  }

可变参数的特点和要求:

(1)一个方法最多只能有一个可变参数

(2)如果一个方法包含可变参数,那么可变参数必须是形参列表的最后一个

(3)在声明它的方法中,可变参数当成数组使用

(4)其实这个书写...

【修饰符】 返回值类型 方法名(【非可变参数部分的形参列表,】参数类型[] 形参名){ }

只是后面这种定义,在调用时必须传递数组,而前者更灵活,既可以传递数组,又可以直接传递数组的元素,这样更灵活了。

1.1 方法只有可变参数

案例:求 n 个整数的和

public class SumToolss {
    // 数组求和
    public int sum1(int[] arr) {
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum += arr[i];
        }
        return sum;
    }

    // 一个一个输入  ...
    // 可变参数当作数组来使用
    public int sum2(int... num) {
        int sum = 0;
        for (int i = 0; i < num.length; i++) {
            sum += num[i];
        }
        return sum;
    }
}
import day0412.model.SumToolss;

public class TestSumToolss {
    public static void main(String[] args) {
        SumToolss sumtools = new SumToolss();
        int[] arr = {1, 2, 3, 4, 5};
        int rel1 = sumtools.sum1(arr);
        int rel3 = sumtools.sum2(2, 12, 3, 4, 5, 6);
        int rel2 = sumtools.sum3(2, arr);
        int rel4 = sumtools.sum3(2, 12, 3, 4, 5, 6);
        System.out.println(rel1);
        System.out.println(rel2);
        System.out.println(rel3);
        System.out.println(rel4);
    }
}

1.2 方法包含非可变参数和可变参数

  • 非可变参数部分必须传入对应类型和个数的实参;

  • 可变参数部分按照可变参数的规则传入0~n个对应类型的实参或传入1个对应类型的数组实参;

案例:

        n个字符串进行拼接,每一个字符串之间使用某字符进行分割,如果没有传入字符串,那么返回空字符串""

public class StringTools {
    // n 个字符串进行拼接,每一个字符串之间用某个字符进行分割
    // 如果没有传入字符串,那么返回空字符串""
    public String concat(String st, String... arr) {

        String str = "";
        for (int i = 0; i < arr.length; i++) {
            if (i == 0) {
                str += arr[i];
            } else {
                str += st + arr[i];
            }
        }
        return str;
    }
}

public class TestStringToolss {
    // public class StringTools {
    // n 个字符串进行拼接,每一个字符串之间用某个字符进行分割
    // 如果没有传入字符串,那么返回空字符串""
    public static String concat(String st, int... arr) {

        String str = " ";
        for (int i = 0; i < arr.length; i++) {
            if (i == 0) {
                str += arr[i];
            } else {
                str += st + arr[i];
            }
        }
        return str;
    }

    // }
    public static void main(String[] args) {
        // StringTools st = new StringTools();
        //String[] arr = {"123", "456", "789"};
        System.out.println(concat("-", 1));// 1
    }
}

2.特殊参数之二:命令行参数(了解)

        通过命令行给main方法的形参传递的实参称为命令行参数

public class SpeParam {
    // 直接接受 args ,命令行参数
    // 直接通过命令行给 main 方法的形参传递的实参为命令行参数
    // String...args
    // JDK 1.0 main方法就有了  15
    // 1.只有一个可变参数  2.有多个参数时,可变参数放置最后一个  3.main 主执行程序的参数(命令行参数) String...args
    public static void main(String[] args) {
        for (int i = 0; i < args.length; i++) {
            System.out.println(args[i]);
        }
    }
}

命令行:

java TestCommandParam
java TestCommandParam 1 2 3
java TestCommandParam hello haog

3.方法的参数传递机制

方法的参数传递机制:实参给形参赋值,那么反过来形参会影响实参吗?

  • 方法的形参是基本数据类型时,形参值的改变不会影响实参;

  • 方法的形参是引用数据类型时,形参地址值的改变不会影响实参,但是形参地址值里面的数据的改变会影响实参,例如,修改数组元素的值,或修改对象的属性值。

  • 注意:String、Integer等特殊类型容易错

3.1 形参是基本数据类型

public void swapData2(int a, int b) {
    // 两两交换,使用中间值
    // 局部的区域
    int temp;
    temp = a;
    a = b;
    b = temp;
    System.out.println("交换之后的x:" + a);
    System.out.println("交换之后的y:" + b);
}

public class TestCahngeData {
    public static void main(String[] args) {
        ChangeData ch = new ChangeData();
        int x = 2;
        int y = 3;
        // 这个在内存中属于不同的区域
        // 全局的量区域  不同的
        ch.swapData2(x, y);
        System.out.println("交换之前的x:" + x);
        System.out.println("交换之前的y:" + y);
    }
}

3.2 形参是数组

public int[] swapData(int[] arr) {
    // 两两交换,使用中间值
    // 局部的区域
    System.out.println(arr[0]);
    System.out.println(arr[1]);
    int temp;
    temp = arr[0];
    arr[0] = arr[1];
    arr[1] = temp;
    return arr;
}
public class TestCahngeData2 {
    public static void main(String[] args) {
        ChangeData ch = new ChangeData();
        String[] arr = {"5", "6"};
        System.out.println("下面是交换之前的数据:");
        ch.itra(arr);
        System.out.println("下面是交换之后的数据:");
        ch.swapData(arr);
        ch.itra(arr);
    }
}

3.3 形参是引用数据类型

public int[] swapData(String[] arr) {
    // 两两交换,使用中间值
    // 局部的区域
    System.out.println(arr[0]);
    System.out.println(arr[1]);
    String temp;
    temp = arr[0];
    arr[0] = arr[1];
    arr[1] = temp;
    return arr;
}

public class TestCahngeData2 {
    public static void main(String[] args) {
        ChangeData ch = new ChangeData();
        String[] arr = {"5", "6"};
        System.out.println("下面是交换之前的数据:");
        ch.itra(arr);
        System.out.println("下面是交换之后的数据:");
        ch.swapData(arr);
        ch.itra(arr);
    }
}

3.4 形参指向新对象

// 对象的值传递过来  引用数据类型传递也是地址  修改的数据与传递数据也是一致的
public void swapData3(MyData my) {
    // 两两交换,使用中间值
    // 局部的区域
    // 新开辟一个空间就不行了   my= new myData();
    int temp;
    temp = my.x;
    my.x = my.y;
    my.y = temp;

    System.out.println("交换之后的x:" + my.x);
    System.out.println("交换之后的y:" + my.y);
}

public class MyData {
    public int x;
    public int y;
}

public class TestChangeData3 {
    public static void main(String[] args) {
        ChangeData ch = new ChangeData();
        MyData myData = new MyData();
        myData.x = 7;
        myData.y = 8;

        System.out.println("操作之前x:" + myData.x);
        System.out.println("操作之前y:" + myData.y);
        ch.swapData3(myData);
    }
}

4.方法的重载

  • 方法重载:指在同一个类中,允许存在一个以上的同名方法,只要它们的参数列表不同即可,与修饰符和返回值类型无关。

  • 参数列表:数据类型个数不同,数据类型不同(按理来说数据类型顺序不同也可以,但是很少见,也不推荐,逻辑上容易有歧义)。

  • 重载方法调用:JVM通过方法的参数列表,调用匹配的方法。

    • 先找个数、类型最匹配的

    • 再找个数和类型可以兼容的,如果同时多个方法可以兼容将会报错

案例,用重载实现:

(1)定义方法求两个整数的最大值

(2)定义方法求三个整数的最大值

(3)定义方法求两个小数的最大值

(4)定义方法求n个整数最大值

public class MathTools {
    //求两个整数的最大值
    public int max(int a,int b){
        return a>b?a:b;
    }

    //求两个小数的最大值
    public double max(double a, double b){
        return a>b?a:b;
    }

    //求三个整数的最大值
    public int max(int a, int b, int c){
        return max(max(a,b),c);
    }

    //求n整数的最大值
    public int max(int... nums){
        int max = nums[0];//如果没有传入整数,或者传入null,这句代码会报异常
        for (int i = 1; i < nums.length; i++) {
            if(nums[i] > max){
                max = nums[i];
            }
        }
        return max;
    }
}

4.1 找最匹配的

public class SuperMarket {
    // 支付方法 pay
    // 1个 String 参数
    public String pay(String type) {
        return "所有超市都支持" + type;
    }

    // 2个 String 参数
    public String pay(String type1, String type2) {
        return "所有超市都支持" + type1 + ",还支持" + type2;
    }

    // 1个 float 参数
    public String pay(float money) {
        return "今天我去超市花费了" + money + "元";
    }

    public String pay(String... type) {
        /*// String str = "";
        if (type == null || type.length == 0) {
            return "";
        } else {
            String str = type[0];
            for (int i = 0; i < type.length; i++) {
                str += type[i];
            }
            return "所有超市都支持:" + str;
        }*/
        String str = "";
        for (int i = 0; i < type.length; i++) {
            str += type[i];
        }
        return "所有超市都支持:" + str;
    }
}

public class TestSuperMarket {
    public static void main(String[] args) {
        SuperMarket market = new SuperMarket();
        String rel1 = market.pay("现金");
        System.out.println(rel1);// 所有超市都支持现金

        String rel2 = market.pay("现金", "刷卡");
        System.out.println(rel2);// 所有超市都支持现金,还支持刷卡

        String rel3 = market.pay(131.4f);
        System.out.println(rel3);// 今天我去超市花费了131.4元

        String rel4 = market.pay("现金", "、支付宝", "、微信");
        System.out.println(rel4);// 所有超市都支持:现金、支付宝、微信
        String rel5 = market.pay();
        System.out.println(rel5);// 所有超市都支持:
    }
}

4.2 找唯一可以兼容的

package com.haogu.test06.overload;
​
public class MethodOverloadMostCompatible {
    public static void main(String[] args) {
        MathTools tools = new MathTools();
​
        System.out.println(tools.max(5.7,9));
        System.out.println(tools.max(5,6,8,3));
//        System.out.println(tools.max(5.7,9.2,6.9)); //没有兼容的
    }
}

5.方法的递归调用

递归调用:方法自己调用自己的现象就称为递归。

递归的分类:

  • 递归分为两种,直接递归和间接递归。

  • 直接递归称为方法自身调用自己。

  • 间接递归可以A方法调用B方法,B方法调用C方法,C方法调用A方法。

注意事项

  • 递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出。

  • 在递归中虽然有限定条件,但是递归深度不能太深,否则效率低下,或者也会发生栈内存溢出。

    • 能够使用循环代替的,尽量使用循环代替递归

案例:计算斐波那契数列(Fibonacci)的第n个值,斐波那契数列满足如下规律,

1,1,2,3,5,8,13,21,34 ....

即从第三个数开始,一个数等于前两个数之和。假设f(n)代表斐波那契数列的第n个值,那么f(n)满足:

f(n) = f(n-2) + f(n-1);

public class Feibo {
    long fei(int n) {
        // 小于 1
        if (n < 1) {
            return 0;
        }
        // 等于 1或者 等于 2
        if (n == 1 || n == 2) {
            return 1;
        }
        return fei(n - 2) + fei(n - 1);
        /*
        fei(5)
        第一次:fei(3)+fei(4)
        第二次:fei(1)+fei(2)+fei(2)+fei(3)
        第三次:fei(1)+fei(2)+fei(2)+fei(1)+fei(2)
        */
    }

    public static void main(String[] args) {
        // 计算斐波那契额数列的第 n 个值,满足一下规律:1,1,2,3,5,8,13,21  f(n)=f(n-2)+f(n-1)
        Feibo feibo = new Feibo();
        System.out.println(feibo.fei(5));
        System.out.println(feibo.fei(6));
        System.out.println(feibo.fei(48));
    }
}

6.对象数组

数组是用来存储一组数据的容器,一组基本数据类型的数据可以用数组装,那么一组对象也可以使用数组来装。

即数组的元素可以是基本数据类型,也可以是引用数据类型。当元素是引用数据类型是,我们称为对象数组。

注意:对象数组,首先要创建数组对象本身,即确定数组的长度,然后再创建每一个元素对象,如果不创建,数组的元素的默认值就是null,所以很容易出现空指针异常NullPointerException。

6.1 对象数组的声明和使用

案例:

(1)定义矩形类,包含长、宽属性,area()求面积方法,perimeter()求周长方法,String getInfo()返回圆对象的详细信息的方法

(2)在测试类中创建长度为5的Rectangle[]数组,用来装3个矩形对象,并给3个矩形对象的长分别赋值为10,20,30,宽分别赋值为5,15,25,遍历输出

public class Dog {
    // 狗的名字
    public String name;
    // 狗的年龄
    public int age;
}

public class TestDog2 {
    public static void main(String[] args) {
        Dog[] dog = new Dog[5];
        // 数组对象中得先设置值,然后再使用对象中的属性和方法
        // 对象排序时,是比较对象的属性值
        Dog dog1 = new Dog();
        // 第一个
        dog1.name = "花花";
        dog1.age = 2;
        dog[0] = dog1;
        // 第二个
        Dog dog2 = new Dog();
        dog2.name = "老黄";
        dog2.age = 10;
        dog[1] = dog2;
        // 第三个
        Dog dog3 = new Dog();
        dog3.name = "小白";
        dog3.age = 7;
        dog[2] = dog3;
        // 第四个
        Dog dog4 = new Dog();
        dog4.name = "小红";
        dog4.age = 4;
        dog[3] = dog4;
        // 第五个
        Dog dog5 = new Dog();
        dog5.name = "小黑";
        dog5.age = 5;
        dog[4] = dog5;

        // 根据狗的年龄进行狗的对象数据的排序
        for (int i = 0; i < dog.length - 1; i++) {
            for (int j = 0; j < dog.length - i - 1; j++) {
                if (dog[j].age > dog[j + 1].age) {
                    Dog temp = new Dog();
                    temp = dog[j];
                    dog[j] = dog[j + 1];
                    dog[j + 1] = temp;
                }
            }
        }

        String dogMsg = "";
        for (int i = 0; i < dog.length; i++) {
            dogMsg += dog[i].name + dog[i].age + "岁\t";
        }
        System.out.println(dogMsg);
    }
}

后续内容,正在更新...

  • 13
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值