栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

可变参数(varags)的代码技巧

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

可变参数(varags)的代码技巧

文章目录

前言

一、避免带有可变参数的方法重载

1.可变参数与非可变参数的方法重载

示例:

思考:

结果:

2.可变参数与可变参数的方法重载

示例:

思考:

结果:

二、带有可变参数的方法重写

1.方法重写

示例:

思考:

结果:

总结

参考文献


前言

在项目和系统的开发中,为了提高代码的灵活性和可复用性,我们经常要传递不确定量的参数到方法中,可变参数(varags)的引人实现了这一需求。当然可变参数也是要遵循一定规则的,比如可变参数必须是方法的最后一个参数;一个方法不能定义多个可变参数等。这些基本规则需要牢记,但及时记住了这些规则,仍然有可能出现错误。

本文将介绍可变参数的部分使用技巧。


一、避免带有可变参数的方法重载

1.可变参数与非可变参数的方法重载

示例:
public class VaragsDemo {

    public void sale(Double price){
        Double discountedPrice = price * 0.9;
        System.out.println("单间商品折后价格" + discountedPrice);
    }

    public void sale(Double...prices){
        Double sumPrice = 0.0;
        for (Double price : prices) {
            sumPrice += price;
        }
        Double discountedPrice = sumPrice * 0.8;
        System.out.println("多件商品折后价格" + discountedPrice);
    }

}

示例中定义了用于计算折后商品价格的方法sale()。根据买的商品数量不同,所打的折扣也不同。单件商品打9折,而多件商品则打8折。其中两个方法“方法名相同,参数类型或数量不同”,符合方法重载的定义。

思考:

执行以下代码的结果会是如何?

public class Test {

    public static void main(String[] args) {
        VaragsDemo varagsDemo = new VaragsDemo();
        //买了一件90元的商品
        varagsDemo.sale(90.0);
    }
    
}

这里我们希望调用单件商品的折扣方法,但仔细想一下,这次的方法重载似乎有些特殊。方法sale(Double...prices)参数范围覆盖了sale(Double price),即这里调用两个方法的哪一个都有可能,这大大降低了代码的可读性,且容易出错。

结果:
单间商品折后价格81.0

从结果可以看出,代码确实按照我们的预想完成了单件商品的折扣计算。这是因为Java在编译时,首先会根据实参的数量和类型进行处理,这里的90.0被当做Double类进行了装箱,而非被当做一个Double数组,因此调用了sale(Double price)方法。而之所以没有被当做数组,是因为编译器会从最简单的开始“猜想”,只要符合编译条件即可通过。

虽然代码的运行与我们的需求相同,但这里考虑到代码的可读性等问题,依然不建议对带有可变参数的方法进行重载。

2.可变参数与可变参数的方法重载 示例:
public class VaragsDemo {

    public void methodA(String str,Integer...i){}

    public void methodA(String str,String...strs){}

}

在示例中对两个methodA()方法进行了重载,接下来看看他们的编译情况。

思考:

以下代码是否可以通过编译?

public class Test {

    public static void main(String[] args) {
        VaragsDemo varagsDemo = new VaragsDemo();
        varagsDemo.methodA("hello",1998);
        varagsDemo.methodA("hello","world");
        varagsDemo.methodA("hello");
        varagsDemo.methodA("hello",null);
    }

}

这里根据不同的参数类型对methodA()方法进行了四次调用,按理说四种参数都能找到对应的方法签名(Method Signature),那么是否全部可以通过编译呢?

结果:

其中varagsDemo.methodA("hello")和varagsDemo.methodA("hello",null)编译报错。

对于varagsDemo.methodA("hello"),由于两个方法都符合形参格式,编译器不知道该调用哪个方法,因此报错。要知道可变参数的数量可以是0个,而一个符合规范的方法居然出错了,这显然是不应该出现的。因此不建议对带有可变参数的方法进行重载。

而对于varagsDemo.methodA("hello",null),直接量null是没有类型的,因此两个方法都符合形参格式,编译器不知道该调用哪个方法,因此报错。可以修改为如下形式,声明null的类型,这不仅可以通过编译,也有助于代码的理解。

public class Test {

    public static void main(String[] args) {
        VaragsDemo varagsDemo = new VaragsDemo();
        String strs = null;
        varagsDemo.methodA("hello",strs);
    }

}

二、带有可变参数的方法重写

1.方法重写 示例:
public class Base {

    public void demo(String...strs){
        System.out.println("Base类的Demo方法");
    }

}

public class Sub extends Base{

    @Override
    public void demo(String[] strs){
        System.out.println("Sub类的Demo方法");
    }

}

在示例中定义父类Base类和子类Sub类,在子类中对demo()方法完成了重写。我们知道重写方法时,参数列表必须与被重写方法相同,那么在此处@Override注解是否会报错呢?其实父类的demo()方法编译成字节码后的形参是一个String类型的数组,这和子类的参数列表相同,因此这里的重写符合规范,@Override注解没有问题。

思考:

以下代码是否能通过编译?

public class Test {

    public static void main(String[] args) {
        Base base = new Sub();
        base.demo("Hello");

        Sub sub = new Sub();
        sub.demo("Hello");
    }

}

这里分别通过多态形式和普通形式创建了两个Sub类的对象,分别调用demo()方法,是否都可以通过编译并执行呢?

结果:

其中base.demo("Hello")可以通过编译,并正常执行。这是由于可变参数在编译时,将String类型的"Hello"编译成了String数组,再由子类Sub完成执行。

而直接用子类调用的sub.demo("Hello")则不能通过编译,这是因为编译器没有把String类型的"Hello"编译成String数组,参数类型不匹配,编译器自然会拒绝。

同样的方法名,同样的参数,通过父类可以调用,而通过子类则不能调用。重写方法的参数列表居然与父类不同,这违背了重写的定义。因此在对带有可变参数的方法进行重写时,需注意参数的形式。


总结

本文主要总结了几条可变参数的使用技巧。

1.不要对带有可变参数的方法进行重载。

2.重写可变参数的方法时,要注意参数形式。


参考文献

[1]秦小波.编写高质量代码[M]:机械工业出版社

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1024430.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号