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

Android 面试题咨询 “编译中生成的类,怎么让外部调用(不能先编译)”

  •  
  •   zpxshl · 2021-01-17 15:42:29 +08:00 · 10261 次点击
    这是一个创建于 1390 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题。 某大厂的面试题, 求大佬指点下思路或者给个关键字。

    第 1 条附言  ·  2021-01-23 13:24:41 +08:00
    感谢 1,5,11 楼的答案,尤其是 11 楼提供的思路,顺着 ButterKnife.bind()查下去就明白了。
    如 5 楼所说,这题应该是考察 ButterKnife 等使用 apt 的库的原理。
    20 条回复    2021-01-23 13:25:23 +08:00
    skyinu
        1
    skyinu  
       2021-01-17 15:54:56 +08:00 via iPhone   ❤️ 1
    写一个中间类提供给外部调用?中间类自己反射调用生成类?
    woodnaonly
        2
    woodnaonly  
       2021-01-17 16:02:03 +08:00 via Android
    依赖 jar 不编译
    xcstream
        3
    xcstream  
       2021-01-17 16:44:05 +08:00
    private class
    john6lq
        4
    john6lq  
       2021-01-17 19:14:42 +08:00 via iPhone
    原谅我题目都看不太懂😭
    loshine1992
        5
    loshine1992  
       2021-01-17 19:34:23 +08:00   ❤️ 1
    这个问的是 ButterKnife 等使用 APT 的库的原理
    zpxshl
        6
    zpxshl  
    OP
       2021-01-17 20:43:35 +08:00
    @loshine1992 大佬,能稍微展开讲讲吗? 我看了 ButterKnife 的原理,生成 r2 和代码,r2 只是为了让编译通过(注解不能使用变量,因此不能用 R )。 生成的代码里面还是使用了 R.id.xxxx 。 可这和题目有啥关系...
    nnqijiu
        7
    nnqijiu  
       2021-01-17 21:07:14 +08:00
    编译中生成的类是啥意思?
    zpxshl
        8
    zpxshl  
    OP
       2021-01-17 21:07:53 +08:00
    @nnqijiu 有些类是编译阶段才生成的。 比如 R.java
    liuzhedash
        9
    liuzhedash  
       2021-01-17 22:04:21 +08:00
    问就是反射
    fox0001
        10
    fox0001  
       2021-01-17 23:05:21 +08:00 via Android
    编译生成的类,继承已生成的父类或者接口,可以不?除了把数据编译进方法中,没想到有什么好处…
    twoyuan
        11
    twoyuan  
       2021-01-17 23:32:10 +08:00   ❤️ 1
    应该是 #1 、#5 说的类似 ButterKnife 实现的这种方式,根据注解生成了类,实际对生成的类调用时使用反射。

    很久不用这个库了,可以顺着 ButterKnife.bind 入口往里翻就能找到答案(如果它没改实现方案的话)
    Guaidaodl
        12
    Guaidaodl  
       2021-01-17 23:42:48 +08:00   ❤️ 2
    通常来说这种问题有两个方向. 一个是注解(Annotation), 另外一个是 Ttransform.

    1. 注解的处理流程是在编译之前的. 所以其实你就直接引用你要生成的类就好. 因为注解在编译前处理, 所以编译是可以正常通过的. 如果不想在 build 之前 Android Studio 显示错误的话, 通常偷取一个接口和一个工厂类 /方法, 里面会用放射的方式来创建实现类.

    2. Transform 流程可以直接修改字节码, 是在编译成 class 文件后进行的. 这里通常就是反射加工厂了.

    还有一种可能是 SPI. 不过 SPI 的实现通常都是手写的实现的. 很少是编译期间生成的.
    zpxshl
        13
    zpxshl  
    OP
       2021-01-18 00:10:42 +08:00 via Android
    @twoyuan 感谢,明早我看下 bufferknife 的源码,之前对它的分析停留在几篇文章上......
    lxilu
        14
    lxilu  
       2021-01-18 00:50:03 +08:00 via iPhone
    什么叫不能先编译?
    kingfalse
        15
    kingfalse  
       2021-01-18 08:22:41 +08:00 via Android
    运行时动态编译?
    Cabana
        16
    Cabana  
       2021-01-18 09:01:32 +08:00 via Android
    1,接口
    2,反射
    wjploop
        17
    wjploop  
       2021-01-18 09:45:38 +08:00
    编译前和编译后处理的对象分别是*.java 和*.class,这里要求编译前,可以使用解析 java 文件的库[javaparser]( https://javaparser.org/),类似 Jsoup 于*.xml
    unco020511
        18
    unco020511  
       2021-01-18 14:23:44 +08:00
    对不起,我连题目都没看明白
    Anarchy
        19
    Anarchy  
       2021-01-18 18:55:03 +08:00 via Android
    编译中生成的只是 ide 不提示你知道也可以写代码正常走编译流程。如果是动态加载的就搞个中间类反射调用。
    zpxshl
        20
    zpxshl  
    OP
       2021-01-23 13:25:23 +08:00
    @twoyuan ButterKnife.bind 顺着这入口,很快就找到答案了,感谢!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3139 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 12:36 · PVG 20:36 · LAX 04:36 · JFK 07:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.