V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
kop1989
V2EX  ›  Java

这样的重载写法是如何通过编译的?

  •  
  •   kop1989 · 2021-09-28 15:31:58 +08:00 · 3570 次点击
    这是一个创建于 1141 天前的主题,其中的信息可能已经有所发展或是发生改变。
    楼主对 j2SE 的理解非常浅薄,还停留在 2010 年。

    最近需要接入各个渠道的推送,在接入小米渠道时,发现其 sdk 混淆后的一个类,很有意思。
    这个类的具体类名是:com.xiaomi.mipush.sdk.PushMessageHandler

    这个类中有两个方法,分别为:

    protected static void b() {synchronized (a) {a.clear();} }

    public static boolean b() {return b.isEmpty();}

    这样写并不符合 java 的重载语法吧?
    既两个方法只有返回值不同,换句话说二者的方法签名是一致的。
    但神奇的是,当我引入这个 jar 包到 java 项目中时,竟然可以编译通过。

    反之,当我把这个 jar 引入到 Xamarin Android 项目中时,就会因为有两个 b()编译失败。

    求各路大神解答。
    18 条回复    2021-09-28 22:37:25 +08:00
    humpy
        1
    humpy  
       2021-09-28 15:40:01 +08:00
    方法签名不同啊
    wangxn
        2
    wangxn  
       2021-09-28 15:43:53 +08:00 via Android
    C++不能这样,指不定 Java 可以。
    humpy
        3
    humpy  
       2021-09-28 15:46:48 +08:00
    @humpy #1 sorry,我看错了
    tsanie
        4
    tsanie  
       2021-09-28 15:57:13 +08:00
    这么神奇的嘛,那在这个类或其子类中调用 b()到底执行哪个方法? /doge
    mxT52CRuqR6o5
        5
    mxT52CRuqR6o5  
       2021-09-28 15:59:50 +08:00
    android java 是不是和原版 java 有点区别?
    BQsummer
        6
    BQsummer  
       2021-09-28 16:00:42 +08:00
    artifactId 和 version 是啥
    ipwx
        7
    ipwx  
       2021-09-28 16:01:10 +08:00
    盲猜字节码层面可能有些不一样(我不懂 java )
    ligiggy
        8
    ligiggy  
       2021-09-28 16:05:48 +08:00
    我也不懂 java,但是有没有一种可能,我是说有没有一种可能,synchronized 这个用法会被编译器优化
    yazinnnn
        9
    yazinnnn  
       2021-09-28 16:10:27 +08:00
    gav 坐标发一下看看
    wangsilence
        10
    wangsilence  
       2021-09-28 16:27:57 +08:00
    我本地试了 编译不通过啊
    xiaxiaocao
        11
    xiaxiaocao  
       2021-09-28 16:36:36 +08:00   ❤️ 7
    JVM 里方法签名是包含返回值类型的,返回值类型不同,方法签名不同,可以同时存在。不能存在不同返回值类型的相同 Java 方法是 Java 语言层面的限制,也即 javac 编译的限制。直接操作字节码可以写出这样方法,是完全合法的。
    kop1989
        12
    kop1989  
    OP
       2021-09-28 16:45:05 +08:00
    @xiaxiaocao #11 学习了,能不能大概说说这样做的意义和场景?
    nonoyang
        13
    nonoyang  
       2021-09-28 17:49:34 +08:00
    如果编译通过,直接调用 PushMessageHandler.b(),忽略返回值,你觉得代码能知道该调用哪个?
    ipwx
        14
    ipwx  
       2021-09-28 18:22:31 +08:00
    @nonoyang 一个 protected 一个 public,外部函数自然知道调用哪个。
    evi1j
        15
    evi1j  
       2021-09-28 18:36:46 +08:00 via Android
    java 泛型的桥接模式也有这种情况,javap 之后就会看到有签名相同的方法
    maokabc
        16
    maokabc  
       2021-09-28 19:35:20 +08:00 via Android
    不是返回值不同吗?一个方法签名()V,一个()Z,java 层面不能这样写,字节码可以。
    再说了内部类有时生成一些方法名和方法签名完全一样的方法,就访问控制符多了 bridge 之类,之前做安卓的加固遇到过,怕出问题就没把 bridge 这类方法转为 native 。
    secondwtq
        17
    secondwtq  
       2021-09-28 22:23:02 +08:00
    有点像 C++ 的 name mangling
    leaves615
        18
    leaves615  
       2021-09-28 22:37:25 +08:00
    字节码混淆(压缩)过的 jar 。 不能直接反编译过来用的。
    下一个问题。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5344 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 07:17 · PVG 15:17 · LAX 23:17 · JFK 02:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.