Выполнение вычислений может привести к сценарию, где вычисленный результат выходит за границы диапазона типа данных переменной результата. В Java, если целые значения достигают своих пределов, то они имеют неприятную особенность переходить к противоположной границе. Чтобы проиллюстрировать это, рассмотрим код следующего класса:
// OverflowEX.java
public class OverfTowEX {
publiс static void main(String args []) {
byte x = 0;
for (int i = 0; i < 130; i++) {
x++;
System.out.println(x);
}
}
}
Как
известно,
byte
в Java является 8-битовым типом данных со знаком. Это означает, что диапазон значений
byte
лежит от -128 до 128. Результатом добавления единицы к любой границе заданного диапазона целого типа будет другая граница диапазона целого типа. Поэтому в этом примере добавление 1 к 127 создаст -128. И если откомпилировать и выполнить эту программу, то последние пять чисел выведенные на консоли будут следующими:
126
127
– 128
– 127
– 126
Это может оказаться весьма существенной проблемой, особенно в связи с тем, что ни предупреждение ни исключение не порождаются, чтобы позволить обработать такое событие (возможно, сохраняя значение в типе с большим диапазоном значений). По умолчанию C# также обрабатывает ситуации переполнения, но язык и компилятор предоставляют инструменты для явной обработки и уведомления программиста в случае переполнения.
□ Программный подход. Чтобы бороться с этим типом молчаливых ошибок, C# вводит концепцию проверяемых и непроверяемых инструкций. Ключевое слово
checked
используется для управления контекстом проверки переполнения в случае операций и преобразований арифметики целого типа, таких, как представленные выше. Оно может использоваться как оператор или как инструкция. Инструкции
checked/unchecked
следуют приведенному ниже синтаксису (
i
). Они предназначены для помещения в скобки ряда инструкций, которые могут создавать переполнение. Синтаксис операции
checked/unchecked
показан в пункте (
ii
). Операция checked проверяет переполнение одиночных выражений:
(i) checked {block_of_code}
unchecked { block_of_code}
(ii) checked (expression)
unchecked (expression)
block_of_code
содержит код, в котором инструкция
checked/unchecked
наблюдает за переполнением, a
expression
представляет выражение, в котором
checked/unchecked
наблюдает за переполнением в конечном значении. Показанный далее пример иллюстрирует использование
checked/unchecked
:
// OverflowEX.cs
public class OverflowEX {
public static void Main(String args) {
sbyte x = 0; //
помните, что необходимо изменить byte на sbyte
for (int i = 0; i < 130; i++) {
checked {
// можно также использовать checked(x++)
x++;
Console.WriteLine(x);
}
}
}
}
□ Подход с ключом компилятора. Для контроля переполнения во всем приложении может использоваться настройка компилятора
/checked+
. Чтобы проиллюстрировать это, удалим инструкцию
checked
из приведенного выше примера и попытаемся компилировать его, используя флаг
/checked+
. С его помощью можно включать и выключать проверку арифметического переполнения, изменяя состояние конфигурационных свойств на странице свойств проекта. Задание значения как true будет включать проверку переполнения.
При включенной проверке переполнения можно обсудить использование инструкции
unchecked
. По сути она предоставляет функциональность для произвольного исключения проверки выражений или блоков инструкций в то время, когда включена проверка во всем приложении. В примере ниже предыдущая инструкция заменяется инструкцией
unchecked
. Компиляция и выполнение этого кода будет создавать вывод, аналогичный выводу
OverflowEX.java
.
// OverflowEX.сs.
public class OverflowEX {
public static void Main(String[] args) {
sbyte X = 0;
for (int i = 0; i < 130; i++) {
unchecked { // можно также использовать unchecked(x++)
x++;
Console.WriteLine(x);
}
}
}
}
Входные и выходные данные
Возможность собрать входные данные из командной строки и вывести данные в командной строке является интегральной частью функциональности ввода/вывода в Java. Обычно в Java необходимо создать экземпляр объекта
java.io.BufferedReader
, используя поле
System.in
, чтобы извлечь ввод из командной строки. Ниже представлен простой класс Java —
JavaEcho
, который получает ввод с консоли и выводит его обратно, чтобы проиллюстрировать использование пакета