Задачи на JPoint 2018. Luxoft. День 1

Задача 1

public class Quiz_1 {

    public static void main(String[] args) {
        String s = null;
        System.out.println(s instanceof String);
    }
    
}

Варианты ответов:

  1. true
  2. false
  3. NullPointerException
  4. Compilaction error
Правильный ответ

2. false

Согласно пункту документации 15.20.2. Type Comparison Operator instanceof:

At run time, the result of the instanceof operator is true if the value of the RelationalExpression is not null and the reference could be cast (§15.16) to the ReferenceType without raising a ClassCastException.


Задача 2

public class Quiz_2 {

    public static void main(String[] args) {
        String[] strings = {"1", "1"};
        Object[] objects = strings;
        objects[0] = 0;
        System.out.println(
                Arrays.toString(objects)
        );
    }
    
}

Варианты ответов:

  1. [0, 2]
  2. [1, 2]
  3. Runtime exception
  4. Compilation error
Правильный ответ

3. Runtime exception

Аналогичный пример даже указан в javadoc для класса java.lang.ArrayStoreException


Задача 3

public class Quiz_3 {

    public static void main(String[] args) {
        String str = "true";
        if ("t" + "r" + "u" + "e" == "true")
            System.out.print("1");
        if (str + "" == "true")
            System.out.print("2");
        if (str.replace('T', 't') == "true")
            System.out.print("3");
    }
    
}

Варианты ответов:

  1. 123
  2. 12
  3. 23
  4. 13
  5. 1
  6. 2
  7. 3
Правильный ответ

4. 13

  1. Выражение "t" + "r" + "u" + "e" является строковым литералом и согласно спецификации 3.10.5. String Literals:
    A long string literal can always be broken up into shorter pieces and written as a (possibly parenthesized) expression using the string concatenation operator +
    [...]
    Moreover, a string literal always refers to the same instance of class String.
    
        Strings computed by constant expressions (§15.28) are computed at compile time and then treated as if they were literals.
        Strings computed by concatenation at run-time are newly created and therefore distinct.
    

    Более того, компилятор самостоятельно вычислить выражение и в байт-код запишет следующее:

       L0
        LINENUMBER 15 L0
        LDC "true"
        ASTORE 1
       L1
        LINENUMBER 17 L1
        GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
        LDC "1"
        INVOKEVIRTUAL java/io/PrintStream.print (Ljava/lang/String;)V
    

    L0 соответствует сохарнению значения «true» в переменную, а L1 соответствует выводу «1» через System.out, любые проверки отсутствуют.

  2. Компилятор вместо оператора конкатенации «+» в байт-коде использует java.lang.StringBuilder:
       L2
        LINENUMBER 18 L2
        NEW java/lang/StringBuilder
        DUP
        INVOKESPECIAL java/lang/StringBuilder. ()V
        ALOAD 1
        INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
        LDC ""
        INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
        INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
        LDC "true"
        IF_ACMPNE L3
    

    Метод StringBuilder.toString() возвращает новый экземпляр типа String с новой ссылкой:

    @Override
    public String toString() {
        // Create a copy, don't share the array
        return new String(value, 0, count);
    }
    

    Именно поэтому сравнение через == вернёт значение false.

  3. В соответствии с javadoc метода replace():
    If the character {@code oldChar} does not occur in the character sequence represented by this {@code String} object, then a reference to this {@code String} object is returned.
    

    Поскольку 'T' отсутствует в исходной строке, то вернётся исходный объект.


Задача 4

public class Quiz_4 {

    public static void main(String[] args) {
        Stream stream =
                Stream.of("A", "B");
        System.out.print(1);
        stream.peek(System.out::print);
        System.out.print(2);
        stream.forEach(System.out::print);
    }
    
}

Варианты ответов:

  1. 1AB2AB
  2. 1A2A1B2B
  3. 12AB
  4. 12ABAB
  5. Runtime exception
  6. Compilation error
Правильный ответ

5. Runtime exception

А конкретно:

Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
	at java.util.stream.AbstractPipeline.sourceStageSpliterator(AbstractPipeline.java:279)
	at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
	at me.markoutte.sandbox.conferences.jpoint2018.luxoft.day1.Quiz_4.main(Quiz_4.java:21)

Происходит это всё из-за того, что peek является промежуточной операцией, возвращающей новый стрим, который в данном примере отсутствует, а вызов forEach обнаруживает проблему чтения из того же стрима, что читает peek.


Задача 5

public class Quiz_5 {

    public static void main(String[] args) {
        HashSet set = new HashSet<>();
        for (short i = 0; i < 100; i++) {
            set.add(i);
            set.remove(i - 1);
        }
        System.out.println(set.size());
    }
    
}

Варианты ответов:

  1. 0
  2. 1
  3. 100
  4. Runtime exception
  5. Compilation error
Правильный ответ

3. 100

Ни одно из значений не будет удалено из сета, поскольку для операции (i - 1) будет автоматически выполнено сначала расширения типа до integer, а потом боксинг в тип Integer. Поскольку в сете хранится тип Short, а не Integer, то ни одна из операций по удалению не сможет найти нужных значений и величина массива будет равна количеству операции по добавлению. В данном случае таковых 100.

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: