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

215 天前
 shucc
public static final int FIRST_LINE_HEIGHT = ScreenUtil.dp2px(80);

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

4527 次点击
所在节点    Android
14 条回复
dqzcwxb
215 天前
ScreenUtil.dp2px()的问题
TArysiyehua
215 天前
楼上+1
chendy
215 天前
默认情况下,静态变量初始化不结束,类加载不结束,外部访问不了这个类
所以更可能发生的情况是,某些地方用反射破了 final 修改了这个值…
Ianchen
215 天前
典型的 DCL ( double check lock )问题吧?
lff0305
215 天前
遇到过类似的问题,原因是多个类在 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;
}
}
winterbells
215 天前
可能 static 加载的时候 activity 还没启动,设置为-1 ,在 oncreate 里面设置,或者读取的时候判断一下
cyningxu
215 天前
检查 ScreenUtil.dp2px
oneisall8955
215 天前
瞎猜一下加个 volitate 防止指令重排?
lisongeee
215 天前
不能像 kotlin 一样使用 lazy 去加载吗?
silkgrower
214 天前
@lff0305 我觉得这层答案对的.跟 Java 加载类的顺序有关.
q1angch0u
214 天前
static 的变量在类加载阶段 [加载-连接-初始化] 中的连接阶段中的 [准备] 阶段就会做赋值。
q1angch0u
214 天前
补充一下,final 的 static 变量会在 [准备] 阶段赋值,非 final 的会在 [准备] 阶段赋零值,然后在 [初始化] 阶段的 [clinit] 中赋值。
chendy
214 天前
@lff0305 静态引用环,恐怖如斯…
nothingistrue
214 天前
你这个很明显跟 public static final int FIRST_LINE_HEIGH 没关系,跟 ScreenUtil.dp2px(80) 有关系。

80dp 的高度如果是静态值,那么请直接把它赋值给 FIRST_LINE_HEIGHT 。如果是动态值,那么请不要赋值给 static final 类型的「常量」,给常量设置一个可变值,即使是仅取第一次的值,那也是找抽。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/980330

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX