Ответ 1
Для переключателя по строке
class Fun {
static int fun(String s) {
switch (s) {
case "I":
return 1;
case "A":
return 2;
case "Z":
return 3;
case "ABS":
return 4;
case "IND":
return 5;
default:
return 6;
}
}
}
Компилятор Oracle Java генерирует байт-код, похожий на следующий код (Eclipse Compiler for Java генерирует несколько другой байт-код)
int c = -1;
switch (s.hashCode()) {
case 65: // +1 branch
if (s.equals("I")) // +2 branches
c = 0;
break;
case 73: // +1 branch
if (s.equals("A")) // +2 branches
c = 1;
break;
case 90: // +1 branch
if (s.equals("Z")) // +2 branches
c = 2;
break;
case 64594: // +1 branch
if (s.equals("ABS")) // +2 branches
c = 3;
break;
case 72639: // +1 branch
if (s.equals("IND")) // +2 branches
c = 4;
break;
default: // +1 branch
}
switch (c) {
case 0: // +1 branch
return 1;
case 1: // +1 branch
return 2;
case 2: // +1 branch
return 3;
case 3: // +1 branch
return 4;
case 4: // +1 branch
return 5;
default: // +1 branch
return 6;
}
Итак, исходный оператор switch с 6 случаями представлен в байт-кодере с помощью переключателя с 6 случаями для hashCode
of String
плюс 5 if-statements плюс еще один переключатель с 6 случаями. Чтобы увидеть этот байт-код, вы можете использовать javap -c
.
JaCoCo выполняет анализ байт-кода и в версиях ниже 0.8.0 не имеет фильтра для переключения по строкам. Ваши тесты охватывают случаи, когда условия в if-statements оцениваются до true
, но не в тех случаях, когда они оцениваются до false
. Лично я бы посоветовал просто игнорировать недостающие случаи, потому что цель состоит не в том, чтобы проверить, что компилятор генерирует правильный код, а для проверки правильности поведения вашего приложения. Но ради полноты этого ответа - вот тесты, которые охватывают все ветки байткода:
import org.junit.Test;
import static org.junit.Assert.*;
public class FunTest {
@Test
public void test() {
// original strings:
assertEquals(1, Fun.fun("I"));
assertEquals(2, Fun.fun("A"));
assertEquals(3, Fun.fun("Z"));
assertEquals(4, Fun.fun("ABS"));
assertEquals(5, Fun.fun("IND"));
// same hash codes, but different strings:
assertEquals(6, Fun.fun("\0I"));
assertEquals(6, Fun.fun("\0A"));
assertEquals(6, Fun.fun("\0Z"));
assertEquals(6, Fun.fun("\0ABS"));
assertEquals(6, Fun.fun("\0IND"));
// distinct hash code to cover default cases of switches
assertEquals(6, Fun.fun(""));
}
}
И отчет, созданный JaCoCo 0.7.9 в качестве доказательства:
JaCoCo версии 0.8.0 предоставляет фильтры, включая фильтр для байт-кода, который javac
производит для переключения по строка. И поэтому генерирует следующий отчет даже без дополнительных тестов: