Ответ 1
Компилятор Java переводит код коммутатора либо в tableswitch
, либо в lookupswitch
.
tableswitch
используется, когда между различными случаями существует только несколько пробелов. В противном случае используется lookupswitch
.
В вашем случае используется tableswitch
, потому что хэш-коды ваших случаев расположены близко друг к другу (в отличие от кода, на который ссылается owaism):
16: tableswitch { // 68 to 83
68: 111 // 'D'
69: 183
70: 141 // 'F'
71: 96 // 'G'
72: 183
73: 183
74: 183
75: 183
76: 183
77: 126 // 'M'
78: 183
79: 183
80: 183
81: 183
82: 171 // 'R'
83: 156 // 'S'
default: 183
}
Цифрами слева от двоеточия являются упорядоченные хеш-коды и заполненные промежутки между ними, номера справа - это точки перехода. (В Java хэш-код символа является его значением ASCII.)
68
- это хеш-код "D" (самый низкий), а 83
- хеш-код "S" (самый высокий).
69
- это значение одного из промежутков между реальными случаями и перейдет к случаю по умолчанию.
Однако я предполагаю, что EclEmma исключает эти ветки из расчета покрытия tableswitch
(это снизит охват еще больше из-за разрывов).
Итак, у нас есть ветки 0 (подсчитаны).
Затем сравнивается сравнительное сравнение строкового значения в каждом месте назначения перехода (за исключением одного случая по умолчанию). Поскольку ваш коммутационный корпус состоит из 6 случаев, у нас есть 6 шести пунктов назначения прыжка с равным сравнением.
Байт-код сравнения для случая "G" ниже:
96: aload_3
97: ldc #10
99: invokevirtual #11 java/lang/Object;)Z
102: ifeq 183
105: iconst_0
106: istore 4
108: goto 183
111: aload_3
EclEmma рассчитывает две ветки: либо входная строка, и строка case равны, либо они не являются. Таким образом, для сравнений мы имеем 6 * 2 ветвей. (Случай по умолчанию не веткится.)
Далее, если две строки равны, индекс файла будет сохранен (строки байтового кода 105-106
для случая "G" ). Затем будет выполнен переход к второму tableswitch
. В противном случае скачок будет выполнен непосредственно.
185: tableswitch { // 0 to 5
0: 224
1: 237
2: 250
3: 263
4: 276
5: 289
default: 299
}
Этот переключатель работает с индексом ранее сохраненного случая и переходит к коду в случае (регистр "G" имеет индекс 0
, случай по умолчанию имеет -1
). EclEmma считает 7 ветвей (6 случаев плюс случай по умолчанию).
Следовательно, мы имеем 0 подсчитанных ветвей в первых tableswitch
, 12 ветвях в сравнении equals
и еще 7 ветвей во втором tableswitch
. В общем, этот приводит к 19 ветвям.
Тестирование не распространяется ни на одну из 6 ветвей без равенства. Чтобы их охватить, вам нужно найти строку для каждого случая, которая не равна условию case, но имеет тот же хэш-код. Возможно, но окончательно неразумно...
Вероятно, подсчет ветвей EclEmma будет скорректирован в будущем.
Кроме того, я полагаю, у вас нет тестового примера, который не соответствует ни одному из случаев (таким образом, (неявный) случай по умолчанию не распространяется.)