среда, 10 августа 2022 г.

Оператор ветвления if..else в Java

   Оператор с условием "Если" - if.

    В Java оператор if может сопровождаться дополнительным оператором else, который выполняется при ложном логическом выражениив результате.

   Синтаксис:

   if (Логическое выражение) { 

      //Выполняется, если истинно

    } else { //Выполняется, если ложно }

 

   Объединяющие условие "и" выглядит так:

 if (a && b)

 

   Объединяющие условие "или" выглядит так:

if (a || b)

суббота, 6 августа 2022 г.

Операции в Java

Операция присвоения =
 
  Операция "=" позволяет присвоить значение переменной
   (Пример: int x=3; )
 

Арифметические преобразования

   Арифметические преобразования обозначаются так:

   +   сложение
   -   вычитание
   *   умножение
   /   деление
   %   взятие остатка от деления: выдает остаток от деления: (5%3=2); (24%7=3);

   (Пример: double x3 = 1.1 * 2 + 1;  )

   NB!: При выполнении арифметических операций над операндами с различными типами данных результат будет иметь наибольший тип из типов данных операнд.
    При выполнении арифметических операций операнды всегда преобразуются как
минимум в int (например при умножении двух переменных типа byte оба значения сначала преобразуются в int, и результат выражения будет int).

   При выполнении арифметической операции над операндами разных типов результат операции будет иметь наибольший тип, Что можно описать следующими правилами:

 1. Если один из операндов имеет тип double, то результат выражения
    имеет тип double, иначе смотри пункт 2.
 2. Если один из операндов имеет тип float, то результат выражения имеет
    тип float, иначе смотри пункт 3.
 3. Если один из операндов имеет тип long, то результат выражения имеет
    тип long, иначе результат выражения имеет тип int.

(например, при сложении int  и long  результат будет иметь тип long, а при сложении long  и float  результат будет иметь тип float, а при сложении float  и double  результат будет иметь тип double).

   Если результат операции с целочисленными данными выходит за диапазон, то старшие биты отбрасываются, и результирующее значение будет совершенно неверным. При попытке деления на 0 возникает исключение java.lang.ArithmeticException/zero.

   При выполнении операций с плавающей точкой при выходе за верхнюю или
нижнюю границу диапазона получается +Infinity  (
Double.POSITIVE_INFINITY  и Float.POSITIVE_INFINITY) и -Infinity  (
Double.NEGATIVE_INFINITY  и Float.NEGATIVE_INFINITY ) соответственно, а при получении слишком маленького числа, которое не может быть нормально сохранено в этом типе данных получается -0.0 или +0.0.

   При выполнении операций с плавающей точкой результат NaN  ( Double.NaN и Float.NaN) получается в следующих случаях:

  * Когда один из операндов |NaN|
  * В неопределённых результатах:
      o Деления 0/0, ∞/∞, ∞/−∞, −∞/∞,  −∞/−∞
      o Умножения 0×∞ and 0×−∞
      o Степень 1^∞
      o сложения ∞ + (−∞), (−∞) + ∞ и эквивалентные вычитания.
  * Операции с комплексными результатами:
      o Квадратный корень из отрицательного числа
      o Логарифм отрицательного числа
      o Тангенс 90 градусов и ему подобных (или π/2 радиан)
      o Обратный синус и косинус от числа меньше −1 и больше +1.



Унарные операции

   Унарными называются операции, которые имеют только один операнд. Унарные
операции бывают префиксные и постфиксные.

   Постфиксные унарные операции ставятся после операнда:

  * Инкремент (увеличение на 1) ++
  * Декремент (уменьшение на 1) --


Примеры:

Java
int x = 3;
short y = 100;
x++; // после выполнения x становится равным 4.
y--; // после выполнения y становится равным 99.

    Префиксные унарные операции ставятся перед операндом:
 
+    Унарный плюс (обозначает положительные числа, хотя числа положительными будут и без него)
-    Унарный минус (обозначает отрицательные числа)
!    Логическое НЕ (инвертирует значение логического типа, превращая true  в false и наоборот)
++ Префиксный инкремент (увеличивает значение на 1)
--   Префиксный декремент (уменьшает значение на 1)


Примеры:

Java
int x1 = +10; // положительная десятка
int x2 = -x1; // -10

boolean b1 = true
boolean b2 = !b1; // false

++x1; // теперь x1 равен 11.
--x2; // теперь x2 равен -11


Отличие постфиксного и префиксного инкремента и декремента


   С виду может показаться, что префиксный и постфиксные инкремент и декремент одинаковы, но это не так. Их отличие в том, что префиксный инкремент и декремент возвращают значение, которое получилось после операции увеличения и уменьшения соответственно, а постфиксный инкремент и декремент возвращают исходное значение, которое было до увеличения или
уменьшения.

Пример:

Main.java
Java
class Main {
    public static void main(String[] args) {
        int x1 = 100;
        int x2 = 145;
       
        int y1 = ++x1;
        int y2 = --x2;

        // Вывод для префиксных операций
        System.out.println("\nPrefix ++, -- test");
        System.out.println("x1=" + x1 + "; y1=" + y1);
        System.out.println("x2=" + x2 + "; y2=" + y2);

        // Возвращаем исходные значения
        x1 = 100;
        x2 = 145;
  
        int z1 = x1--;
        int z2 = x2++;

        // Вывод для постфиксных операций
        System.out.println("\nPostfix ++, -- test");
        System.out.println("x1=" + x1 + "; z1=" + z1);
        System.out.println("x2=" + x2 + "; z2=" + z2);
    }
}


Этот пример выводит в консоль следующее:

Prefix ++, -- test
x1=101; y1=101
x2=144; y2=144

Postfix ++, -- test
x1=99; z1=100
x2=146; z2=145


    Как видно из примера y1 и y2 стали равны  значениям x1 и x2, которые получились после осуществления операций инкремента и декремента соответственно, а z1  и z2  стали равны значениям x1 и x2, которые были до операций инкремента и декремента.
 


Операции сравнения

   Операции сравнения позволяют проверить, больше ли один операнд другого, либо что один операнд равен другому и т. д.

Вот список операций сравнения в Java:

   = =  равенство (нужно использовать два символа равно для сравнения, а не один)
   !=  неравенство
   >  больше
   >=  больше или равно
   <  меньше
   <=  меньше или равно
 
   Данныеоперации сравнения используются для чисел, т.к. оператор == сравнивает не свойства объектов (строк), а ссылки (адреса в памяти).


   Все операции сравнения возвращают логическое значение boolean, что означает, что результат операции сравнения можно присвоить переменной этого типа и использовать в любом месте, где требуется значение типа boolean.

Пример:

class Main {
    public static void main(String[] args) {
        int x = 3;
        double d = 3.1;
        System.out.println(x == d); // false
        System.out.println(x > d);  // false
        System.out.println(x < d);  // true
    }
}

При сравнении используются следующие правила:

  * Если один из операндов NaN, то результат false.
  * -Infinity  меньше +Infinity
  * -0.0 с плавающей точкой равен +0.0 с плавающей точкой
  * При сравнении примитивов разных типов значение меньшего типа
    преобразуется в больший тип.



Логические операторы в Java
 
&      Логическое AND (И)
&&   Сокращённое AND
|        Логическое OR (ИЛИ)
||        Сокращённое OR
^       Логическое XOR (исключающее OR (ИЛИ))
!       Логическое унарное NOT (НЕ)
&=   AND с присваиванием
|=      OR с присваиванием
^=     XOR с присваиванием
==     Равно
!=      Не равно
?:       Тернарный (троичный) условный оператор
 
 
   Логические операторы &, |, ^ действуют применительно к значениям типа boolean точно так же, как и по отношению к битам целочисленных значений.
 
 
 
Логические И и ИЛИ

   Логическое И &&  и Логическое ИЛИ || ведут себя вполне ожидаемо для логического И или логического ИЛИ:

Java
boolean b1 = true && true; //true
boolean b2 = true && false; //false
boolean b3 = true || false; // true
boolean b4 = false || false; //false

System.out.println(b1);
System.out.println(b2);
System.out.println(b3);
System.out.println(b4);


    Логическое И &&  вычисляет свой правый операнд только в том случае, если левый равен true. Если левый операнд равен false, то сразу возвращается false. Логическое ИЛИ ||  вычисляет правый операнд только в том случае, если левый равен false. Если левый операнд равен true, то сразу возвращается true. Эти два правила сокращения вычислений позволяют сразу откинуть последующие вычисления, если результат всего выражения уже известен. Это можно использовать для проверки на null  перед проверкой результата какого-либо метода объекта (будет описано в дальнейшем):

Java
if (obj != null && obj.method1()) { // obj.method1() будет вызывать только
                                    // если проверка obj!= null вернула true.
}
 
 
 
Логическое НЕ
 
   Логический оператор ! инвертирует (меняет на противоположный) булево состояние: !true == false и !false == true.



Тернарная операция

   Операция «?:» называется тернарной, потому что он принимает три операнда.

<выражение_boolean> ? <выражение1> : <выражение2>
1
   
<выражение_boolean> ? <выражение1> : <выражение2>

   Тернарная операция вычисляет <выражение_boolean>, если оно равно true, то вычисляет и возвращает <выражение1>, а если false, то <выражение2> .

Java
class Main {
    public static void main(String[] args) {
        int x = 3 > 2 ? 5 : -3; // 5
        String str1 = 3 == 2 ? "YES": "NO"; //"NO"
        System.out.println(x);
        System.out.println(str1);
    }
}
 
 
 
 
Операция instanceof

   Операция instanceof  проверяет, является ли объект экземпляром класса или экземпляром дочернего класса или экземпляром класса, реализующего интерфейс.


obj1 instanceof A

Возвращается true, если obj1  не null  и является экземпляром класса A
или экземпляром дочернего класса A  или экземпляром класса, реализующего
интерфейс A.


Object obj1 = new String("test1");
if (obj1 instanceof String) {
    System.out.println("YES");
}

Если левый операнд равен null, то результатом будет false. Код ниже
выведет “NO”:

Object obj1 = null;
if (obj1 instanceof String) {
    System.out.println("YES");
} else {
    System.out.println("NO");
}
 


Битовые (побитовые) операции

   Битовые операции в Java используются редко, но знать их нужно. Работают они также, как и в Javascript.
   Побитовые операции в Java можно проводить только над целочисленными типами данных. То есть long, int, short, char, byte. Разница в работе с целочисленными значениями только в том какой они хранят в себе диапазон допустимых значений.

Битовые операции в Java:

  <<     Битовый сдвиг влево
  <<=   Битовый сдвиг влево с присваиванием
  >>     Битовый знаковый сдвиг вправо
  >>=   Битовый знаковый сдвиг вправо с присваиванием
  >>>   Беззнаковый битовый сдвиг вправо с заполнением нулями. Он отличается от >>  тем, что ставит 0 в самую левую позицию, а >> ставит то, что было в знаковом бите
  >>>=   Беззнаковый битовый сдвиг вправо с заполнением нулями с присваиванием
  ~       Побитовый унарный оператор NOT - инвертация бит (меняет 0 на 1 и 1 на 0 во всех битах)
  &      Побитовый AND (применяет битовую операцию И)
  &=    Побитовый AND с присваиванием
  |        Побитовый OR. Применяет побитовую операцию ИЛИ
  |=      Побитовый OR с присваиванием
  ^       Побитовый исключающий OR. Применяет XOR (исключающее или)
  ^=     Побитовый исключающий OR с присваиванием

   Эти операнды работают так же, как и из аналоги в других языках программирования.

Main.java

class Main {
    public static void main(String[] args) {
        int n1 = 4; // 100 в двоичной системе
        System.out.println("n1 >> 1 = " + (n1 >> 1)); //2 или 10
                                                  // в двоичной системе.


        System.out.println("n1 << 1 = " + (n1 << 1)); ;// 8 или 100
                                                  // в двоичной системе.

        System.out.println("0b101 & 0b100 = " + (0b101 & 0b100)); // 4  (0b100)
        System.out.println("0b001 | 0b100 = " + (0b001 | 0b100)); // 5  (0b101)
        System.out.println("0b1110 ^ 0b1011 = " + (0b1110 ^ 0b1011)); //5 (0b101);

        System.out.println("-2 >> 1 = " + (-2 >> 1)); // -1 (единица со знака
                               // сдвинется вправо, так что знак не поменяется)
                                                     

        System.out.println("-2 >>> 1= " + (-2 >>> 1)); // 2147483647 (сменит
                                // знак, так как левый бит заполнится нулём).

        System.out.println("~1 = " + ~1) ;  // -2 (0b000...001
                                          // превратится в 0b1111..10)     
       
    }
}

   Результаты выполнения побитовых операций:
   Дополнительная информация по битовым операциям: ссылка

 
 
Присвоение с выполнением другой операции
    (Сокращённая запись операций))

    Сокращённые записи операций позволяют сразу выполнить операции и присвоить результат другой переменной:
 
   +=    (сложение с присвоением)
    -=    (вычитание с присвоением)
   *=    (умножение с присвоением)
    /=    (деление с присвоением)
    %=  (взятие остатка с присвоением)
    &=   (битовый И с присвоением)
    ^=    (битовое исключающее ИЛИ с присвоением)
    |=     (битовое ИЛИ с присвоением)
    <<=  (сдвиг влево с присвоением)
    >>=  (знаковый сдвиг вправо с присвоением)
    >>>=  (беззнаковый сдвиг вправо с присвоением)


   Пример: num += 7;  // это эквивалентно num = num + 7



Они работают так:

E1 compop E2
1
   
E1 compop E2
 
что эквивалентно

E1 = (T) E1 op E2;
1
   
E1 = (T) E1 op E2;

, где T  — это тип переменной E1.

То есть intx1+=x3 эквивалентно intx1=(int)x1+x2.

Main.java
Java
class Main {
    public static void main(String[] args) {
        int x1 = 100;
        byte x2 = 100;
        int x3 = 100;
       
        x1 += 300; // эквивалентно x1 = (int) x1 + 300;
        x2 += 300; // эквивалентно x2 = (byte) x2 + 300;      
        x3 += 300.1; // эквивалентно x3 = (int) x3 + 300.1;

        System.out.println("x1=" + x1);  // 400
        System.out.println("x2=" + x2);  // -112
        System.out.println("x3=" + x3);  // 400
    }
}
 
 
 

Приоритеты операций


 
   Все операции вычисляются слева направо (сначала вычисляется левый операнд, затем правый и затем сама операций, кроме операции присваивания. Операция присваивания вычисляется справа налево.

   Вычисления производятся в соответствии с таблицей приоритетов операций, приведённой ниже. Операция, находящаяся выше в таблице, имеет более высокий приоритет, чем операция, находящаяся ниже, и вычиляется раньше.
   Операции, находящиеся на одной строке, имеют одинаковый приоритет. Если в одном выражении находится несколько разных операций, то сначала вычисляется результат операции с наивысшим приоритетом. Можно использовать скобки для указания того, что сначала нужно вычислить эту
часть выражения.

Пример 1:

Java
int z = 200 * (3 + 4);


Последовательность вычисляения такая:

 1. 3+4 = 7
 2. 200 * 7 = 1 400
 3. z = 1 400

Пример 2:

Java
int x;
int y;
int z = x = y = 10000 + 20000 >> 1 + 3 * 2;


Последовательность вычисления такая:

 1. 10 000 + 20 000 = 30 000 (Присвоение вычисляется справа налево,
    поэтому сначала смотрится y=10000+20000>>1+3*2 , и вычисляется
    правая часть. В правой части ( 10000+20000>>1+3*2 ) вычисление идёт
    слева направо, и берётся 10000+20000 (выбирается среди 10000+20000 ,
    20000>>1 , 1+3  и 3*2 ), которое вычисляется перед сдвигом, так как
    у сложения приоритет выше.)
 2. 3 * 2 = 6 (В выражении 30000>>1+3*2 вычисление идёт слева направо, и
    выбирается умножение(среди 30000>>1 , 1+3  и 3*2 ), так как у него
    приоритет выше, что означает, что сложение будет выполнено раньше.)
 3. 1 + 6 = 7 (В выражении 30000>>1+6 вычисление идёт слева направо и
    сложение вычисляется раньше сдвига, так как приоритет у сложения выше.)
 4. 30 000 >> 7 = 234   (0b00…111010100110000 сдвигаем на 7 бит вправо и
    получаем 0b00…0011101010)
 5. y = 234
 6. x = 234
 7. z = 234



Таблица приоритетов операций

Группа операций     Приоритет
Группировка     |/(/ ... /)/|
Доступ к члену     |/.../ . /.../|
постфиксные     |/expr/++ /expr/--|
унарные     |++/expr/ --/expr/ +/expr/ -/expr/ ~ !|
мультипликативные     |* / %|
аддитивные     |+ -|
сдвиги     |<< >> >>>|
сравнения     |< > <= >= instanceof|
равенства     |== !=|
бинарный И     |&|
бинарный исключающее ИЛИ     |^|
бинарный ИЛИ     |||
логический И     |&&|
логический ИЛИ     ||||
тернарный     |? :|
лямбда     |->|
присваивания     |= += -= *= /= %= &= ^= |= <<= >>= >>>=|

Наследование в Java

   «родительское/дочернее»     Наследование (inheritance) - свойство системы, позволяющее описать (создать) новый класс на основе уже су...