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 (count) ветвей еще.
Затем сравнивается сравнительное сравнение строкового значения в каждом пункте назначения перехода (за исключением одного случая по умолчанию). Поскольку ваш коммутационный корпус состоит из 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 подсчитывает две ветви: либо входной строки и случай строки равны или они не являются. Таким образом, у нас есть 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 будет скорректирован в будущем.
Кроме того, я думаю, вы не тест, который не совпадает ни с одним из случаев (таким образом (неявный) по умолчанию случае не охватывается.)
Есть ли шансы 'пос '_variable_ может получить другие буквенные значения? Если да, добавьте случай по умолчанию. – Voqus
Я добавил первую строку кода, в которой указано, как pos определен. Добавление пустого случая по умолчанию ничего не изменило, как я ожидал бы – Gaargod
Я бы посоветовал не тестировать другие ветки. Некоторые конструкции (см. Также Java 7s try with resource) генерируют гораздо более сложный байт-код, чем исходный код. Однако вы можете быть на 100% (нормально 99,99%) уверены, что JRE не ошибается в этом. Поэтому сосредоточьте свои усилия на тестировании в другом месте. – Thirler