Gradle 8.0编译报错:constant expression required问题咨询
Gradle 8.0编译报错:switch case要求常量表达式问题
问题场景
使用Gradle 8.0构建APK时,以下Java代码触发编译错误:
switch (checkedRadioButtonId) { case R.id.radioButtonDate: Collections.sort( inilistdatalist, (s1, s2) - Long.compare( s1.getInifile().lastModified(), s2.getInifile().lastModified())); Collections.sort( FilesHandler.rwiniArr, (s1, s2) - Long.compare( s1.iniFile.lastModified(), s2.iniFile.lastModified())); break; case R.id.radioButtonName: Collections.sort( inilistdatalist, (s1, s2) -> s1.getIniname().compareTo(s2.getIniname())); Collections.sort( FilesHandler.rwiniArr, (s1, s2) - s1.iniFile .getName() .compareTo(s2.iniFile.getName())); break; case R.id.radioButtonSize: Collections.sort( inilistdatalist, (s1, s2) - Long.compare( s1.getInifile().length(), s2.getInifile().length())); Collections.sort( FilesHandler.rwiniArr, (s1, s2) - Long.compare( s1.iniFile.length(), s2.iniFile.length())); break; }
编译错误日志
/storage/emulated/0/AndroidIDEProjects/RWTranslater/app/src/main/java/com/eam/shuangx339/modtranslater/Activity/IniListActivity.java:264: error: constant expression required case R.id.radioButtonDate: ^ /storage/emulated/0/AndroidIDEProjects/RWTranslater/app/src/main/java/com/eam/shuangx339/modtranslater/Activity/IniListActivity.java:278: error: constant expression required case R.id.radioButtonName: ^ /storage/emulated/0/AndroidIDEProjects/RWTranslater/app/src/main/java/com/eam/shuangx339/modtranslater/Activity/IniListActivity.java:290: error: constant expression required case R.id.radioButtonSize: ^
补充说明
radioButtonSize、radioButtonName、radioButtonDate为单选按钮ID,在R文件中是唯一整型值,Gradle 7.x版本下可正常编译,升级到Gradle 8.0后出现上述错误。
原因解析
这是Android Gradle Plugin (AGP) 8.0的默认行为变化:AGP 8.0开始,R类中的资源ID不再是final static修饰的编译时常量,而是变为运行时常量。而Java的switch语法要求case后的表达式必须是编译时常量,因此原来的写法不再符合语法规范。Gradle 7.x对应AGP版本较低,R类资源ID仍为编译时常量,所以能正常编译。
解决方案
方案一:替换为if-else语句(推荐)
if-else对条件表达式没有常量要求,直接替换switch结构即可,同时修正原代码中Lambda表达式的语法错误((s1, s2) -应为(s1, s2) ->):
int checkedRadioButtonId = ...; // 原获取选中按钮ID的代码 if (checkedRadioButtonId == R.id.radioButtonDate) { Collections.sort( inilistdatalist, (s1, s2) -> Long.compare( s1.getInifile().lastModified(), s2.getInifile().lastModified())); Collections.sort( FilesHandler.rwiniArr, (s1, s2) -> Long.compare( s1.iniFile.lastModified(), s2.iniFile.lastModified())); } else if (checkedRadioButtonId == R.id.radioButtonName) { Collections.sort( inilistdatalist, (s1, s2) -> s1.getIniname().compareTo(s2.getIniname())); Collections.sort( FilesHandler.rwiniArr, (s1, s2) -> s1.iniFile .getName() .compareTo(s2.iniFile.getName())); } else if (checkedRadioButtonId == R.id.radioButtonSize) { Collections.sort( inilistdatalist, (s1, s2) -> Long.compare( s1.getInifile().length(), s2.getInifile().length())); Collections.sort( FilesHandler.rwiniArr, (s1, s2) -> Long.compare( s1.iniFile.length(), s2.iniFile.length())); }
方案二:定义编译时常量适配switch
如果坚持使用switch,可以将资源ID赋值给static final修饰的类常量,再用这些常量作为case条件:
// 在当前Activity类中定义编译时常量 private static final int RADIO_BUTTON_DATE = R.id.radioButtonDate; private static final int RADIO_BUTTON_NAME = R.id.radioButtonName; private static final int RADIO_BUTTON_SIZE = R.id.radioButtonSize; // 后续switch代码使用定义的常量 switch (checkedRadioButtonId) { case RADIO_BUTTON_DATE: Collections.sort( inilistdatalist, (s1, s2) -> Long.compare( s1.getInifile().lastModified(), s2.getInifile().lastModified())); Collections.sort( FilesHandler.rwiniArr, (s1, s2) -> Long.compare( s1.iniFile.lastModified(), s2.iniFile.lastModified())); break; case RADIO_BUTTON_NAME: Collections.sort( inilistdatalist, (s1, s2) -> s1.getIniname().compareTo(s2.getIniname())); Collections.sort( FilesHandler.rwiniArr, (s1, s2) -> s1.iniFile .getName() .compareTo(s2.iniFile.getName())); break; case RADIO_BUTTON_SIZE: Collections.sort( inilistdatalist, (s1, s2) -> Long.compare( s1.getInifile().length(), s2.getInifile().length())); Collections.sort( FilesHandler.rwiniArr, (s1, s2) -> Long.compare( s1.iniFile.length(), s2.iniFile.length())); break; }
注意:这种方式依赖编译时资源ID的稳定性,若开启资源混淆可能引发问题,因此优先推荐方案一。
内容的提问来源于stack exchange,提问作者E.A.M
相关产品推荐
相关产品推荐

