The when
inside function extension
equals to if-else syntax, and it works well before API 30 because other newer enum type at below does not exsits so it must be unreachable.
The second function extension2
works well on API 30 or later, but it throws NoSuchFieldError
before API 30.
@SuppressLint("NewApi")
fun Bitmap.CompressFormat.extension(): String {
return when {
this === Bitmap.CompressFormat.JPEG -> ".jpeg"
this === Bitmap.CompressFormat.PNG -> ".png"
this === Bitmap.CompressFormat.WEBP -> ".webp"
// API 30
this === Bitmap.CompressFormat.WEBP_LOSSY -> ".webp"
// API 30
this === Bitmap.CompressFormat.WEBP_LOSSLESS -> ".webp"
else -> throw AssertionError("unreachable code")
}
}
@SuppressLint("NewApi")
fun Bitmap.CompressFormat.extension2(): String {
return when (this) {
Bitmap.CompressFormat.JPEG -> ".jpeg"
Bitmap.CompressFormat.PNG -> ".png"
Bitmap.CompressFormat.WEBP -> ".webp"
// API 30
Bitmap.CompressFormat.WEBP_LOSSY -> ".webp"
// API 30
Bitmap.CompressFormat.WEBP_LOSSLESS -> ".webp"
}
}
I’ve looked at the bytecode of extension2
. There is a synthetic class called $WhenMappings
that calls all the enum types, and I think the hardcode way makes no sense. I mean it’s possible to make WhenMappings
not to hardcode the enums?
public final class XXX$WhenMappings {
// $FF: synthetic field
public static final int[] $EnumSwitchMapping$0 = new int[CompressFormat.values().length];
//.......
static {
//.....
$EnumSwitchMapping$0[CompressFormat.JPEG.ordinal()] = 1;
$EnumSwitchMapping$0[CompressFormat.PNG.ordinal()] = 2;
$EnumSwitchMapping$0[CompressFormat.WEBP.ordinal()] = 3;
$EnumSwitchMapping$0[CompressFormat.WEBP_LOSSY.ordinal()] = 4;
$EnumSwitchMapping$0[CompressFormat.WEBP_LOSSLESS.ordinal()] = 5;
}
}
/*
bytecode
L2
TABLESWITCH
1: L3
2: L4
3: L5
4: L6
5: L7
default: L8
*/