程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

暂无数据

在 Java 中向下转型 + 使用可变参数调用方法

发布于2021-09-19 23:05     阅读(1091)     评论(0)     点赞(1)     收藏(2)


当我调用时a.displayName("Test"),它调用 Icecream 类的方法。displayName(String...s)方法接受可变参数。输出-

test Icecream
test Faloodeh 
test Faloodeh:  Faloodeh
test Faloodeh:  Faloodeh

但是当我将方法更改为displayName(String s)(我已经在代码中注释掉了该部分)时,它会调用 Faloodeh 类的方法。新输出-

test Faloodeh 
test Faloodeh 
test Faloodeh:  Faloodeh
test Faloodeh:  Faloodeh

我想知道为什么会这样。

class Icecream{
    public void displayName(String...s){
        System.out.println(s[0]+" "+"Icecream");
    }
    /*public void displayName(String s){
        System.out.println(s+" "+"Icecream");
    }
    */
    public void describe(String s) {
        System.out.println(s+" "+"Icecream: Ice cream");
    }
}
class Faloodeh extends Icecream {
    public void displayName (String s){
        System.out.println(s+" "+"Faloodeh ");
    }

    public void describe (String s) {
        System.out.println(s+" "+"Faloodeh:  Faloodeh");
    }
}
 class Test {
    public static void main(String arg[]) {
       Icecream a=new Faloodeh ();
       Faloodeh b=( Faloodeh)a;
        a.displayName("test");
        b.displayName("test");
        a.describe("test");
        b.describe("test");
    }
}

**编辑- ** 感谢您的回答。请帮我解决另一个疑问。我将代码更改为 -

class Icecream{
    public void displayName(String s){
        System.out.println(s+" "+"Icecream");
    }
    /*public void displayName(String s){
        System.out.println(s+" "+"Icecream");
    }
    */
    public void describe(String s) {
        System.out.println(s+" "+"Icecream: Ice cream");
    }
}
class Faloodeh extends Icecream {
    public void displayName (String...s){
        System.out.println(s+" "+"Faloodeh ");
    }

    public void describe (String s) {
        System.out.println(s+" "+"Faloodeh:  Faloodeh");
    }
}
 class Test {
    public static void main(String arg[]) {
       Icecream a=new Faloodeh ();
       Faloodeh b=( Faloodeh)a;
        a.displayName("test");
        b.displayName("test");
        a.describe("test");
        b.describe("test");
    }
}

现在这给出了以下输出 -

test Icecream
test Icecream
test Faloodeh:  Faloodeh
test Faloodeh:  Faloodeh

正如你们所解释的,这里 b 是 Faloodeh 类的对象。displayName(String...s)Faloodeh 班级不会被覆盖。仍然在输出中,它显示test Icecream 为什么这样?


解决方案


这里的关键点是,改变displayName(String... s)displayName(String s)原因displayName(String s)的方法Faloodeh覆盖其超类中的方法。

Icecream.displayName(String... s)并且Faloodeh.displayName(String s)具有不同的签名,因此它们不会相互覆盖。但是将前者更改为接受一个String只会导致它们具有相同的签名,从而导致覆盖发生。

在 Java 中,方法调用的解析大致分为三个步骤(有关更多信息:JLS §15.12,我还在此处进行了更详细的解释):

  1. 查找类以搜索适用的方法。这基于您调用方法的对象的编译时类型。在这种情况下,aa的编译时类型是Icecream,因此只会Icecream考虑 的方法。请注意,它没有找到displayName方法,Faloodeh因为 的编译时类型aIcecream
  2. 根据您传递的参数确定要调用的方法的哪个重载。这里只有一种选择。在更改之前和之后,displayName是唯一与您传递的参数兼容的重载。
  3. 根据调用该方法的对象的运行时类型确定要调用该方法的哪个实现。a的运行时类型是Faloodeh. 在改变之前,displayName没有在 中被覆盖Faloodeh,所以它调用了超类的实现。更改后,displayName将被覆盖,因此Faloodeh调用in 的实现

关于您的编辑:

在这种情况下,由于编译时类型bFaloodeh,要搜索的类是Faloodeh(步骤 1)。但是,有 2 种方法与您提供的参数匹配(步骤 2):

  • displayName(String...)Faloodeh, and 中声明
  • displayName(String) 这是继承的。

在这种情况下,编译器总是倾向于没有变量 arity -的重载displayName(String)这在JLS §15.12.2 中有明确规定特别是,步骤 2 进一步分为三个子步骤。第一个子步骤尝试在不允许可变元方法的情况下找到方法,如果任何子步骤找到任何方法,则跳过其余子步骤。



所属网站分类: 技术文章 > 问答

作者:黑洞官方问答小能手

链接:http://www.javaheidong.com/blog/article/290012/05d5ed6eaa2a3f90114e/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

1 0
收藏该文
已收藏

评论内容:(最多支持255个字符)