shucc
V2EX  ›  Android

请求答疑: Java 中 static final 修改常量的加载问题

  •  
  •   shucc · Oct 9, 2023 · 13964 views
    This topic created in 1124 days ago, the information mentioned may be changed or developed.
    public static final int FIRST_LINE_HEIGHT = ScreenUtil.dp2px(80);
    

    我们项目中有以上这一段代码,ScreenUtil.dp2px 即获取 80dp 的高度,存在这个 FIRST_LINE_HEIGHT 数值偶现为 0 的情况,是否是因为 static final 加载时间导致的异常呢?

    14 replies  •  2023-10-10 10:11:03 +08:00
    dqzcwxb
    dqzcwxb
    Oct 9, 2023
    1
    ScreenUtil.dp2px()的问题
    TArysiyehua
    TArysiyehua
    Oct 9, 2023
    2
    楼上+1
    chendy
    chendy
    Oct 9, 2023
    3
    默认情况下,静态变量初始化不结束,类加载不结束,外部访问不了这个类
    所以更可能发生的情况是,某些地方用反射破了 final 修改了这个值…
    Ianchen
    Ianchen
    Oct 9, 2023
    4
    典型的 DCL ( double check lock )问题吧?
    lff0305
    lff0305
    Oct 9, 2023❤️4
    5
    遇到过类似的问题,原因是多个类在 init 的时候互相引用 (有多个 public static final 的 property )。
    例如下面代码打印出来 A 的值是 0

    public class Main {
    public static final int FIRST_LINE_HEIGHT = ScreenUtil.dp2px(80);
    public static void main(String[] argu) {
    }
    }

    class ScreenUtil {
    public static int A = Main.FIRST_LINE_HEIGHT;
    static {
    System.out.println(A);
    }
    public static int dp2px(int i) {
    return i + 1000;
    }
    }
    300
    300
    Oct 9, 2023 via Android
    6
    可能 static 加载的时候 activity 还没启动,设置为-1 ,在 oncreate 里面设置,或者读取的时候判断一下
    cyningxu
    cyningxu
    Oct 9, 2023
    7
    检查 ScreenUtil.dp2px
    itechify
    itechify
    Oct 9, 2023 via Android
    8
    瞎猜一下加个 volitate 防止指令重排?
    lisongeee
    lisongeee
    Oct 9, 2023
    9
    不能像 kotlin 一样使用 lazy 去加载吗?
    silkgrower
    silkgrower
    Oct 9, 2023
    10
    @lff0305 我觉得这层答案对的.跟 Java 加载类的顺序有关.
    runo
    runo
    Oct 10, 2023 via iPhone
    11
    static 的变量在类加载阶段 [加载-连接-初始化] 中的连接阶段中的 [准备] 阶段就会做赋值。
    runo
    runo
    Oct 10, 2023 via iPhone
    12
    补充一下,final 的 static 变量会在 [准备] 阶段赋值,非 final 的会在 [准备] 阶段赋零值,然后在 [初始化] 阶段的 [clinit] 中赋值。
    chendy
    chendy
    Oct 10, 2023
    13
    @lff0305 静态引用环,恐怖如斯…
    nothingistrue
    nothingistrue
    Oct 10, 2023
    14
    你这个很明显跟 public static final int FIRST_LINE_HEIGH 没关系,跟 ScreenUtil.dp2px(80) 有关系。

    80dp 的高度如果是静态值,那么请直接把它赋值给 FIRST_LINE_HEIGHT 。如果是动态值,那么请不要赋值给 static final 类型的「常量」,给常量设置一个可变值,即使是仅取第一次的值,那也是找抽。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   3232 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 64ms · UTC 10:15 · PVG 18:15 · LAX 02:15 · JFK 05:15
    ♥ Do have faith in what you're doing.