Сообщений 54    Оценка 537        Оценить  
Система Orphus

Подготовка к Sun Certified Java Programmer(SCJP) exam.

Автор: Денис Жданов
Enrelia
Опубликовано: 03.01.2007
Исправлено: 10.12.2016
Версия текста: 1.1
Что это такое
Зачем
Процедура сдачи
Подготовка к SCJP 1.4
Exam objectives
Language fundamentals
Declaration and access control
Operators and assignments
Flow control, exceptions and assertions
Object orientation, overloading and overriding, constructors and return types
java.lang – the Math class, Strings and wrappers
Objects and collections
Inner classes
Threads
Подготовка к SCJP 1.5
Exam objectives
Var-args methods
Enums
Covariant returns
Coupling and cohesion
Autoboxing / autounboxing
Overloading rules
Static import
Bitwise operators
Enchanced for loop (for-each)
Compiling assertion-aware code
StringBuilder class
File navigation and I/O
Serialization
Dates, Numbers and Currency
Parsing, Tokenizing and Formatting
Generics
Collections changes
Материалы

Что это такое

Экзамен на SCJP – это тест, проводимый компанией Sun Microsystems, основная цель которого проверить базовые знания языка программирования Java.

Зачем

Минусы

ПРИМЕЧАНИЕ

Все нижесказанное является субъективным мнением автора.

Плюсы

Давайте поговорим подробнее об этом. С минусами понятно (про процедуру сдачи будет рассказано ниже). Давайте разберемся с плюсами. Сразу скажу, что являюсь сторонником сертификации, потому что она мне кажется достаточно объективным критерием оценки человека в профессиональном плане. Человек оценивается всегда, будь то устройство на работу или, например, взятие кредита в банке. Кажется, что дополнительный бонус при этом никогда не будет лишним. Также при подготовке происходит упорядочивание знаний, узнается что-то новое. SCJP необходим для сдачи SCJD, который, в свою очередь, проверяет умение разрабатывать реальные приложения.

Процедура сдачи

  1. На адрес education@Russia.Sun.Com отправляется запрос о приобретении ваучера;
  2. Выставляется счет;
  3. Через некоторое время после оплаты счета(в моем случае примерно месяц) приходит ваучер;
  4. На сайте http://www.2test.com находится наиболее удобный по расположению центр проведения экзамена;
  5. Связываетесь с центром проведения, договариваетесь о времени;
  6. Сдача экзамена ((SCJP 1.5) 72 вопроса, для успешной сдачи необходимо иметь не менее 59% правильных ответов). Каждый вопрос предлагается с вариантами ответов, задача выбрать правильный(ые);

Подготовка к SCJP 1.4

Статья не претендует на то, чтобы быть полным учебником, прочитать который достаточно для прохождения сертификации. Предполагается, что читатель знаком с основными концепциями Java, поэтому о них здесь говориться не будет. Я ставил целью рассказать о тех аспектах, которые не так часто встречаются в повседневной жизни, но знание которых проверяется во время сдачи. Также представлена интересная (на мой взгляд) информация, выходящая за рамки экзамена.

Exam objectives

Language fundamentals

Keywords

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

пример
Which one of these lists contains only Java programming language keywords? (Choose one.)
A. class, if, void, long, Int, continue 
B. goto, instanceof, native, finally, default, throws 
C. try, virtual, throw, final, volatile, transient 
D. strictfp, constant, super, implements, do 
E. byte, break, assert, switch, include
СОВЕТ

Надо не забывать, что есть ключевое слово strictfp, которое означает, что над числами с плавающей точкой должны выполняться точные операции (IEE754). Также надо помнить, что const и goto - ключевые слова, которые не используются, но зарезервированы.

Ключевые слова нельзя использовать в качестве имен переменных и методов. Т.о. увидев пример кода наподобие следующего можно смело утверждать, что он не скомпилируется

пример
          class Foo { 

    publicvoid go() {
        // complex code here 
    }

    publicintbreak(int b) { 
        // code that appears to break something 
    }
}

Хотя null, false и true, строго говоря, являются литералами, в рамках подготовки к экзамену их можно считать ключевыми словами.

СОВЕТ

На экзамене могут быть подводные камни типа использования в примере protect вместо protected, extend вместо extends и т.п.

Legal identifiers

В качестве имен переменных, методов, классов и т.д. можно использовать любую комбинацию символов unicode, чисел и знаков валюты ($) и подчеркивания (_). Причем имя не может начинаться с цифры. Т.о. следующие объявления не вызовут ошибки компиляции:

корректные объявления
          int _a;
int $c;
int ______2_w;
int _$;
int this_is_a_very_detailed_name_for_an_identifier;

а эти вызовут:

некорректные объявления
          int :b;
int -d;
int e#;
int .f;
int 7g;

Literals and ranges of all primitive data types

Здесь надо помнить

          float f = 0.1;
          double d = .5;
          char c = '\u2122';
int i ='\u3100';
          byte b = 128;
short s = '\u8fff';
          char a = 0xFFFF;
char b = 10;

а этот нет

          char c = -1;
char d = 0x10000;

Implicit widening

пример
          byte b = 1;
byte s = 2;
char c1 = b; // Compilation failschar c2 = s; // Compilation fails
пример
          long var = Long.MAX_VALUE;
float f = var;

Array declaration, construction and initialization

String[] names[] // двумерный массив String
СОВЕТ

Скобки после имени переменной относятся только к этой переменной, т.е. при объявлении вида

float[] f1[], f2;

f1 будет двумерный массив, а f2 одномерный.

          int[5] i;
пример
          // агрегатная инициализация
          int[][] scores = {{1, 2}, {1, 2, 3, 4}, {1, 2, 3}};

// создание анонимного массиваvoid test(String[] names) {}
…
test(new String[] {"1", "2"});
пример
          int[] i1 = {1}; // OKint[] i2;
i2 = {1}; // Compilation fails
          new
          int[2] {1, 2};
пример
          int[] i;
char[] c = newchar[2];
i = c;
пример
          class Base {}
class Sub extends Base {}
...
Base[] b;
Sub[] s = new Sub[1];
b = s;
пример
          public
          class StartClass {
    publicstaticvoid main(String[] args) {
        Integer[] intArray = {new Integer(1), new Integer(2)};
        Number[] numberArray = intArray;
        numberArray[0] = new Double(1.0); // java.lang.ArrayStoreException: java.lang.Double
    }
}

Uninitialized variables

Launching JVM

Экзамен предполагает, что испытуемый должен считать, что при запуске JVM должен быть указан класс, в котором затем ищется и запускается метод с сигнатурой

          public
          static
          void main(java.lang.String[] args);
ПРИМЕЧАНИЕ

Вообще говоря, это не совсем так, потому что при работе, например, через JNI наличие main не требуется.

Имя переменной java.lang.String[] может быть любым, т.е. следующий метод будет найден и запущен при старте

          public
          static
          void main(String[] aaa) {}

Исходя из вышесказанного логично, что при запуске следующего примера программа выведет в консоль сообщение об ошибке, потому что метод main, принимающий на вход массив из java.lang.String, в классе StrungOut не определен. Там присутствует метод main, принимающий на вход массив объектов класса String, объявленного в этом же файле:

Exception in thread "main" java.lang.NoSuchMethodError: main
пример
          public
          class StrungOut {
    publicstaticvoid main(String[] args) {
        String s = new String("Hello world");
        System.out.println(s);
    }
}

class String {
    privatefinal java.lang.String s;
    
    public String(java.lang.String s) {
        this.s = s;
    }

    public java.lang.String toString() {
        return s;
    }
}
ПРИМЕЧАНИЕ

Задача выходит из круга рассматриваемых на экзамене.

Declaration and access control

Declarations and modifiers

СОВЕТ

Надо помнить, что если какой-то класс не видит другой, он не видит ни один из его методов независимо от модификатора доступа. Т.е. в следующем примере Bar не скомпилируется, потому что ему не виден весь класс Foo.

Main.java
          package com.mycompany.first

public
          class Main {
}

class Foo {
    publicstaticvoid callMe() {
    }
}
Bar.java
          package com.mycompany.second

          public
          class Bar {
    Bar() {
        Foo.callMe();
    }
}
Base.java
          package pkg1;

publicclass Base {
    protectedint i;
}
Sub1.java
          package pkg2;

import pkg1.Base;

publicclass Sub1 extends Base {

    void test(Base base) {
        System.out.println(base.i); // Compilation fails
    }
}

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

Sub2.java
          package pkg2;

import pkg1.Base;

publicclass Sub2 extends Base {

    void test1() {
        System.out.println(super.i);
    }

    void test2(Sub2 sub) {
        System.out.println(sub.i);
    }
}
модификаторы
          final
          abstract
          strictfp
        
          public
          abstract
          class Foo {
}
ключевые слова
          native
          synchronized
          strictfp
        
пример
          abstract
          class Base {
    publicabstractvoid meth1();
    publicvoid meth2() {}
}

abstractclass Sub extends Base {
    publicvoid meth1() {}
    publicabstractvoid meth2();
}
пример
          public
          class StartClass {
    publicstaticvoid main(String[] args) {
        MyAbstractClass object = new MyAbstractClass(); // Compilations fails
        MyAbstractClass[] array = new MyAbstractClass[4]; // OK
    }
}

abstractclass MyAbstractClass {
}
пример
          public
          class StartClass {
    publicstaticvoid main(String[] args) {
        System.out.println(new B().i);
        // Исправляется так:
        // System.out.println(((A)new B()).i);
    }
}
class A {
    publicint i = 1;
}

class B extends A {
    privateint i = 2;
}
пример
          public
          class StartClass {
    
    privatefinal String DUMMY = "DUMMY";
    
    publicstaticvoid main(String[] args) {
        System.out.println(DUMMY);
    }
}
пример
          public
          class StartClass {
    publicstaticvoid main(String[] args) {
        ((Foo)null).test();
    }
}

class Foo {
    staticvoid test() {
        System.out.println("Foo.test()");
    }
}

Interfaces

пример
          public
          interface Testable {
    int FIELD = 1;
    void test();
}
publicabstractinterface Testable {
    int FIELD = 1;
    void test();
}
publicinterface Testable {
    publicstaticfinalint FIELD = 1;
    void test();
}
publicinterface Testable {
    int FIELD = 1;
    publicabstractvoid test();
}
СОВЕТ

Помните, что все переменные интерфейса public static final, а все методы public. Т.о. следующий код не скомпилируется, потому что пытается изменить терминальное поле counter

пример
          interface Count {
    short counter = 0;
    void countUp();
}

publicclass TestCount implements Count {
    
    publicstaticvoid main(String[] args) {
        TestCount t = new TestCount();
        t.countUp();
    }    
    
    publicvoid countUp() {
        for (int x = 6; x > counter; x--, ++counter) {
            System.out.print(" " + counter);
        }
    }
}

Operators and assignments

Operators

пример
          byte b1 = 1;
byte b2 = 2;
byte b3 = b1 + b2; // possible loss of precision
формула и пример
пример
String s = “abc”;
s += 7.0;
(a / b) * b + (a % b) == a
пример
          int a = 1;
int b = 2;
System.out.println("" + a + b); // prints ‘12’
System.out.println(a + b); // prints ‘3’
пример
          double d1 = 1.5;
double d2 = d1 / 0;
System.out.println(Double.isInfinite(d2)); // trueint i1 = -2;
double d3 = i1 / 0.0;
System.out.println(Double.isInfinite(d3)); // true
пример
          double d1 = Double.NaN;
double d2 = Double.NaN;
System.out.println(d1 == d2); // prints false
System.out.println(Double.isNaN(Float.NaN)); // prints true
пример
          public
          class StartClass {
    publicstaticvoid main(String[] args) {
        finallong MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000;
        finallong MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
        System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);
    }
}
ПРИМЕЧАНИЕ

Задача выходит из круга рассматриваемых на экзамене.

пример
List string = new ArrayList();
System.out.println(string instanceof String);
пример
          public
          class StartClass {

    publicstaticvoid main(String[] args) {
        First first = new First();
        Second second = new Second();
        First anotherFirst = (First)second; // compilation fails
    }
}

class First {
}

class Second {
}
пример
String string = null;
System.out.println(string instanceof String); // false
System.out.println(nullinstanceof String); // false
задача
Может ли оператор >>> вернуть отрицательное число?
ответ
Может: (-1 >>> 32).
задача
Что напечатает программа?
publicclass StartClass {
    publicstaticvoid main(String[] args) {
        int x = 0;
        int y = 0;
        for (int z = 0; z < 5; z++) {
            if ((++x > 2) || (++y > 2)) {
                x++;
            }
        }
        System.out.println(x + " " + y);
    }
}
          long x = 5;
long y = 2;
byte b = (byte) x / y;

Passing variables into methods

пример
          public
          class StartClass {
    publicstaticvoid main(String[] args) {
        String s1 = "java";
        StringBuffer s2 = new StringBuffer("java");
        replaceString(s1);
        replaceStringBuffer(s2);
        System.out.println(s1); // prints 'java'
        System.out.println(s2); // prints 'javac'    
    }

    staticvoid replaceString(String s) {
        s = s.replace('j', 'l');
    }

    staticvoid replaceStringBuffer(StringBuffer s) {
        s.append("c");
        s = new StringBuffer();
        s.append("d");
    }
}

Flow control, exceptions and assertions

if-else branching

пример
          // Что напечатает следующий фрагмент?

          if (exam.done()) 	 
    if (exam.getScore() < 0.61) 	 
        System.out.println(“Try again.”); 	 
else 	 
    System.out.println(“Java master!”);

Надо помнить, что else всегда относится к ближайшему if;

пример
          // Что напечатает следующая программа?
          
public
          class StartClass {
    publicstaticvoid main(String[] args) {
        boolean foo = false;
        if (foo = true) {
            System.out.println("Never prints");
        }
    }
}
пример
          public
          class StartClass {
    publicstaticvoid main(String[] args) {
        int i;
        boolean b = true;
        if (b) {
            i = 1;
        }
        System.out.println(i);
    }
}
ПРИМЕЧАНИЕ

Это относится не только к инициализации переменной внутри if, но и вообще к использованию локальной переменной, которая может быть не инициализирована.

switch statement

пример
          long i = 1;
switch (i) {
    default:
        System.out.println("default");
        break;
}
ПРИМЕЧАНИЕ

Начиная с java 1.5 оператор switch работает также и с перечислениями.

пример
          public
          class StartClass {
    publicstaticvoid main(String[] args) {
        int stage1 = 1;  // исправляется объявлением stage1 final.int i = 1;
        switch (i) {
            case stage1:
                System.out.println("first stage");
                break;
            default:
                System.out.println("default");
                break;
        }
    }
}
пример
          public
          class StartClass {
    publicstaticvoid main(String[] args) {
        char i = 1;
        switch (i) {
            case 0x7fffffff:
                System.out.println("max int");
                break;
            default:
                System.out.println("default");
                break;
        }
    }
}
пример
          public
          class StartClass {
    publicstaticvoid main(String[] args) {
        int i = 1;
        switch (i) {
            default:
                System.out.println("default");
                break;
            case 1:
                System.out.println("first"); // попадем сюда, а не в defaultbreak;
        }
    }
}

Loops

пример
          // Что напечатает программа?

          public
          class Test {
    publicstaticvoid main(String [] args) {
        int i = 1;
        dowhile (i < 1)
            System.out.print("i is " + i);
        while (i > 1) ;
    }
}

Эта программа ничего не напечатает, потому что на самом деле данный код эквивалентен следующему

пример
          public
          class Test {
    publicstaticvoid main(String [] args) {
        int i = 1;
        do {
            while (i < 1) {
                System.out.print("i is " + i);
            }
        } while (i > 1) ;
    }
}
пример
          public
          class StartClass {
    publicstaticvoid main(String[] args) {
        dowhile(false); 
        // можно исправить, записав так// do ; while(false);
    }
}
пример
loop : { // (1)
    System.out.println("test");
    for (;;) {
        break loop;
    }
} // (2)//если бы фигурные скобки в строках (1) и (2) отсутствовали, была бы ошибка компиляции
пример break
          public
          class StartClass {
    publicstaticvoid main(String[] args) {
        boolean isTrue = true;
        outer:
        for (int i = 0; i < 5; i++) {
            while (isTrue) {
                System.out.println("Hello");
                break outer;
            } // end of inner while loop
            System.out.println("Outer loop."); // Won't print
        } // end of outer for loop
        System.out.println("Good-Bye"); // Will print
    }
}
пример continue
          public
          class StartClass {
    publicstaticvoid main(String[] args) {
        outer:
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 5; j++) {
                System.out.println("Hello");
                continue outer;
            } // end of inner loop
            System.out.println("outer"); // Never prints
        }
        System.out.println("Good-Bye");
    }
}
          for ( ; ; ) {}

Handling exceptions

пример
          public
          class StartClass {
    publicstaticvoid main(String[] args) {
        thrownew Throwable();
    }
}
пример
          public
          void test() {
    return;
    System.out.println("test"); // эта строка недостижима
}

Подобное может возникнуть и при обработке исключительных ситуаций. Приведенный ниже код не скомпилируется, потому что контролируемая исключительная ситуация не возбуждается нигде в блоке try, и, следовательно, блок catch по контролируемой исключительной ситуации недостижим

пример
          public
          void test() {
    try {
        System.out.println("Inside empty try");
    } catch(IOException ignore) {
    }
}

Если мы обрабатываем несколько типов исключительных ситуаций, связанных отношением IS-A, надо следить за тем, чтобы обработчик исключительной ситуации общего типа не предшествовал остальным. Приведенный ниже фрагмент не скомпилируется, потому что после обработки java.lang.Exception управление никогда не сможет попасть в обработчик java.lang.IOException (IOException наследник Exception)

пример
          try {
    thrownew IOException();
} catch (Exception e) {
      // operate Exception
} catch (IOException e) {
      // operate IOException
}
СОВЕТ

Надо различать, какой код является достижимым, а какой нет. Например, следующий фрагмент кода скомпилируется, потому что в нем присутствует catch по java.lang.Exception, который сам по себе является контролируемой исключительной ситуацией, но в то же время является родителем неконтролируемой исключительной ситуации java.lang.RuntimeException(и всех потомков этого класса). Компилятор считает, что неконтролируемая исключительная ситуация может возникнуть всегда, и, следовательно, обработчик по java.lang.Exception является достижимым

пример
          public
          void test() {
    try {
        System.out.println("Inside empty try");
    } catch(Exception ignore) {
    }
}
пример
          public
          class StartClass {
    publicstaticvoid main(String[] args) {
        System.out.println(getInt());
    }

    privatestaticint getInt() {
        try {
            return 10;
        } finally{
            return 100;
        }
    }
}
пример
Given the following,

System.out.print("Start ");
try {
    System.out.print("Hello world");
    thrownew FileNotFoundException();
}
System.out.print(" Catch Here ");
catch(EOFException e) {
    System.out.print("End of file exception");
} catch (FileNotFoundException e) {
    System.out.print("File not found");
}

and given that EOFException and FileNotFoundException are both subclasses of IOException, and further assuming this block of code is
 placed into a class, which statement is most true concerning this code?
A. The code will not compile. 	 
B. Code output: Start Hello world File Not Found. 	 
C. Code output: Start Hello world End of file exception. 	 
D. Code output: Start Hello world Catch Here File not found.
ответ

Working with assertions

одно выражение
          public
          double sqrt(double base) {
    assert (0 <= base);
    // some stuff
}
два выражения
          public
          double sqrt(double base) {
    assert (0 <= base) : "Can't calculate square root for the negative number(" + base + ")";
// some stuff
}

Надо помнить, что второе выражение должно возвращать значение. Т.о. следующий пример не скомпилируется, потому что метод foo(), использующийся во втором выражении assert, ничего не возвращает

пример
          public
          class Test {
    publicstaticint y;

    publicstaticvoid foo(int x) {
        System.out.print("foo ");
        y = x;
    }

    publicstaticint bar(int z) {
        System.out.print("bar ");
        return y = z;
    }

    publicstaticvoid main(String [] args) {
        int t = 0;
        assert t > 0 : bar(7);
        assert t > 1 : foo(8);  // Compilation fails
        System.out.println("done ");
    }
}
javac –source 1.4
флаги
-ea   // enables assertions
-enableassertions  // то же, что –ea
-esa // enables assertions for system classes
-enablesystemassertions // то же, что -esa
-da // disables assertions
-disableassertions  // то же, что –da
-dsa // disables assertions for system classes
-disablesystemassertions // то же, что –dsa
java –ea –dsa –da:com.mycompany.myproduct.unchecked...

Object orientation, overloading and overriding, constructors and return types

Overriden methods

ПРИМЕЧАНИЕ

Начиная с джава 1.5 с некоторым ограничением можно менять тип значения, возвращаемого переопределяющим методом. Это называется covariant returns.

пример
          public
          class StartClass {
    publicstaticvoid main(String[] args) {
        Sub sub = new Sub();
        sub.method();
    }
}

class Base {
    privatevoid method() {}
}

class Sub extends Base {
}
новая контролируемая исключительная ситуация
          class Base {
    publicvoid method() {}
}

class Sub extends Base {
    publicvoid method() throws Exception {}
}
более широкий класс конторолируемой исключительной ситуации
          class Base {
    publicvoid method() throws Exception {}
}

class Sub extends Base {
    publicvoid method() throws Throwable {}
}
пример
          class Base {
    publicvoid method() throws Exception {}
}

class Sub extends Base {
    publicvoid method() throws IOException {}
}
пример
          public
          class StartClass {

    publicstaticvoid main(String[] args) {
        Base sub = new Sub();
        sub.test(); // печатается 'Base.test()', потому что вызывается метод класса, определяемого статическим типом переменной (Base)
    }
}

class Base {
    publicstaticvoid test() {
        System.out.println("Base.test()");
    }
}

class Sub extends Base {
    publicstaticvoid test() {
        System.out.println("Sub.test()");
    }
}

Overloaded methods

пример
          class Base {
    publicvoid doStuff(int y, String s) {} 	 
    publicvoid moreThings(int x) {}
}

class Sub extends Base {
    publicvoid doStuff(int y, float s) throws IOException {}
}
пример
          public
          class StartClass {

    privatestaticvoid method(int i) {
        System.out.println("method(int)");
    }

    privatestaticvoid method(long i) {
        System.out.println("method(long)");
    }

    publicstaticvoid main(String[] args) {
        byte b = 1;
        method(b);
    }
}
пример
          public
          class StartClass {

    privatestaticvoid method(Base b) {
        System.out.println("using Base");
    }

    privatestaticvoid method(Sub s) {
        System.out.println("using Sub");
    }

    publicstaticvoid main(String[] args) {
        Base sub = new Sub();
        method(sub);
    }
}

class Base {
}

class Sub extends Base {
}
пример
          public
          class StartClass {
    publicstaticvoid main(String[] args) {
        Animal horse = new Horse();
        horse.eat("grass");
    }
}

class Animal {
    publicvoid eat() {
        System.out.println("Generic Animal Eats Generically");
    }
}

class Horse extends Animal {
    publicvoid eat() {
        System.out.println("Horse eats hay ");
    }

    publicvoid eat(String s) {
        System.out.println("Horse eats " + s);
    }
}
пример
          interface First {
    void method() throws IOException;
}

interface Second {
    void method() throws FileNotFoundException ;
}

class Impl implements First, Second {
    publicvoid method() throws FileNotFoundException {
    }
}

FileNotFoundException потомок IOException, значит их пересечение есть FileNotFoundException. Поэтому метод method() класса Impl не может, например, указать в свой декларации IOException, т.о. следующий код не скомпилируется:

пример
          // …
          class Impl implements First, Second {
    publicvoid method() throws IOException {
    }
}

Constructors and instantiation

пример
          class Base {
    Base(int i) {}
}

class Sub extends Base {
}
пример
          class Base {
    Base(int i) {
        this(i);
    }
}
пример
          public
          class StartClass {

    publicstaticvoid main(String[] args) {
        Sub sub = new Sub();
    }
}

class Base {
    Base() {
        System.out.println("Base c-tor");
    }
}

class Sub extends Base {
    Sub() {
        System.out.println("Sub c-tor");
    }
}
пример
          class Base {
    public Base(String s) {
        System.out.println("Base(" + s + ")");
    }
}

class Sub extends Base {

    privatestaticfinal String CLASS_DUMMY_STRING = "CLASS_DUMMY_STRING";
    privatefinal String INSTANCE_DUMMY_STRING = "INSTANCE_DUMMY_STRING";

    public Sub() {
//        super(INSTANCE_DUMMY_STRING); (1)//        super(getInstanceString());   (2)//        super(CLASS_DUMMY_STRING);    (3)super(getClassString());     // (4)
    }

    privatestatic String getClassString() {
        return CLASS_DUMMY_STRING;
    }

    private String getInstanceString() {
        return INSTANCE_DUMMY_STRING;
    }
}
пример
          Given the following,


          public
          class ThreeConst {
    publicstaticvoid main(String [] args) {
        new ThreeConst();
    }

    publicvoid ThreeConst(int x) {
        System.out.print(" " + (x * 2));
    }

    publicvoid ThreeConst(long x) {
        System.out.print(" " + x);
    }

    publicvoid ThreeConst() {
        System.out.print("no-arg ");
    } 	 
}

what is the result? 	 
A. no-arg 	 
B. 8 4 no-arg 	 
C. no-arg 8 4 	 
D. Compilation fails. 	 
E. No output is produced. 	 
F. An exception is thrown at runtime.

Правильный ответ Е, потому что в классе ThreeConst программистом явно не определен ни один конструктор. То, что похоже на конструкторы, на самом деле методы (у них указан тип возвращаемого значения void), поэтому компилятор сгенерировал конструктор без аргументов, который и был вызван при создании объекта;

java.lang – the Math class, Strings and wrappers

Strings

пример
String x = "Java";
x.concat(" Rules!");
System.out.println("x = " + x);  // the output is: x = Java
x.toUpperCase();
System.out.println("x = " + x);  // the output is still: x = Java
x.replace('a', 'X');
System.out.println("x = " + x);  // the output is still: x = Java
пример
          public
          class StartClass {
    publicstaticvoid main(String[] args) {
        String string1 = "Java";
        String string2 = "Java";
        String string3 = new String("Java");
        String string4 = new String("Java");
        System.out.println(string1 == string2); // true
        System.out.println(string1 == string3); // false
        System.out.println(string3 == string4); // false
        System.out.println(string1.equals(string3)); // true
        System.out.println(string3.equals(string4)); // true
    }
}
пример
String x = "test";
System.out.println(x.length);  // compiler error 	 
String [] y = new String[3];
System.out.println(y.length());  // compiler error
пример
          public
          class StartClass {
    publicstaticvoid main(String[] args) {
        StringBuffer buffer1 = new StringBuffer("aa");
        StringBuffer buffer2 = new StringBuffer("aa");
        System.out.println(buffer1.equals(buffer2)); // Prints false.
    }
}

java.lang.Math class

методы
ceil()
floor()
random()
abs()
max()
min()
round()
sqrt()
toDegrees()
toRadians()
tan()
sin()
cos()

Могут попасться вопросы наподобие нижеприведенного:

пример
          public
          class Degrees {
    publicstaticvoid main(String [] args) {
        System.out.println(Math.sin(75));
        System.out.println(Math.toDegrees(Math.sin(75)));
        System.out.println(Math.sin(Math.toRadians(75)));
        System.out.println(Math.toRadians(Math.sin(75)));
    }
}
what line will the sine of 75 degrees be output?
ответ

Wrapper classes

пример
Integer i = new Integer("0xff");
System.out.println(i.intValue());
пример
Integer i1 = new Integer("042");
Integer i2 = new Integer(042);
System.out.println(i1.equals(i2));
пример
Boolean b = new Boolean("TruE");

СОВЕТ

В 1.4 нельзя использовать объект Boolean в качестве условия в условном операторе, т.о. следующее вызовет ошибку компиляции:

пример
Boolean b = Boolean.TRUE;
if (b) {
    System.out.println("ok");
}
пример
          public
          class StartClass {
    publicstaticvoid main(String[] args) {
        Integer var1 = new Integer(5);
        Long var2 = new Long(5);
        System.out.println(var1.equals(var2));  // Prints false
    }
}

Objects and collections

методы
        boolean equals(Object obj) 	 
void finalize() 	 
int hashCode() 	 
finalvoid notify() 	 
finalvoid notifyAll() 	 
finalvoid wait() 	 
String toString()
вопрос
Does the following hashCode() implementation legal?

publicint hashCode() {
    return 1;
}
ответ
пример
Given the following,
        
1. publicclass X { 	 
2.     publicstaticvoid main(String [] args) { 	 
3. 	       X x = new X(); 	 
4. 	       X x2 = m1(x); 	 
5. 	       X x4 = new X(); 	 
6. 	       x2 = x4; 	 
7. 	       doComplexStuff(); 	 
8. 	   }
9. 	   static X m1(X mx) { 	 
10.        mx = new X(); 	 
11. 	return mx; 	 
12.    } 	 
13. }

After line 6 runs. how many objects are eligible for garbage collection?
ответ
пример
Given:
class CardBoard {

    StringBuffer story = new StringBuffer(“text”);

    CardBoard go(CardBoard cb) {
        cb = null;
        return cb;
    }

    publicstaticvoid main(String[] args) {
        CardBoard c1 = new CardBoard();
        CardBoard c2 = new CardBoard();
        CardBoard c3 = c1.go(c2);
        c1 = null;
        // do stuff
    } 
}

When // do stuff is reached, how many objects are eligible for GC?

A. 0
B. 1
C. 2
D. Compilation fails.
E. It is not possible to know.
F. An exception is thrown at runtime.
ответ
пример
Given the following,
        
1. 	class X { 	 
2. 	    public X x; 	 
3. 	    publicstaticvoid main(String [] args) { 	 
4. 	        X x1 = new X(); 	 
5. 	        X x2 = new X(); 	 
6. 	        x1.x = x2; 	 
7. 	        x2.x = x1; 	 
8. 	        x1 = new X();
9. 	        x2 = x1; 	 
10. 	 // doComplexStuff(); 	 
11. 	} 	 
12. }

after line 9 runs, how many objects are eligible for garbage collection?
ответ
СОВЕТ

Такой набор объектов называется islands of isolated objects.

Inner classes

Inner Classes (none-static inner classes)	 
Method-local Inner Classes 	 
Anonymous Inner Classes 
Static Nested Classes
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        TestOuter myObject = new TestOuter();
        myObject.testOuter(1);
        myObject.new TestInner(2); // (2)new TestOuter().new TestInner(3); // (3)

    }
}

class TestOuter {
    publicclass TestInner {
        public TestInner(int i) {
            System.out.println("Hello from inner class (" + i + ")");
        }
    }

    publicvoid testOuter(int i) {
        new TestInner(i); // (1)
    }
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        new TestOuter().new TestInner().testInner();
    }

}

class TestOuter {
    publicclass TestInner {
        publicvoid testInner() {
            System.out.println("Inner class reference: " + this);
            System.out.println("Outer class reference: " + TestOuter.this);
        }
    }
}
пример
        class TestOuter {
    publicclass TestInner {
        //static int i1 = 4; // (1)staticfinalint i2 = 4;
        //static void test() {} // (2)
    }
}
пример
        class TestOuter {
    void testOuter(int i) {
        class TestInner {
            void testInner() {
                System.out.println("parameter = " + i);
            }
        }
        new TestInner().testInner();
    }
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        TestOuter.TestInner inner = new TestOuter.TestInner();
        TestOuter testOuter = new TestOuter();
        TestOuter.TestInner inner2 = testOuter.new TestInner(); // compilation fails
    }
}

class TestOuter {
    staticclass TestInner {
    }
}

Threads

конструкторы
Thread()
Thread(Runnable target) 	 
Thread(Runnable target, String name) 	 
Thread(String name) 	 
Thread(ThreadGroup group, Runnable target) 	 
Thread(ThreadGroup group, Runnable target, String name) 	 
Thread(ThreadGroup group, String name)
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) throws InterruptedException {
        Thread t = new Thread() {

            publicvoid run() {
                try {
                    sleep(Long.MAX_VALUE);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        t.start();
        Thread.sleep(1000);
        t.setName("MyThread"); // Ok
        t.setDaemon(true); // produces IllegalThreadStateException
    }
}
повторный запуск запущенного потока
        public
        class StartClass {
    publicstaticvoid main(String[] args) throws InterruptedException {
        Thread t = new Thread() {

            publicvoid run() {
                try {
                    sleep(Long.MAX_VALUE);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        t.start();
        t.start(); // produces IllegalThreadStateException
    }
}
повторный запуск завершившегося потока
        public
        class StartClass {
    publicstaticvoid main(String[] args) throws InterruptedException {
        Thread t = new Thread();
        t.start();
        t.join();
        t.start(); // produces IllegalThreadStateException
    }
}
пример
        int i = 1;
synchronized(i) { // compilation fails
    System.out.println("test");
}
пример
        class Test {
    
    staticsynchronizedvoid test1() {} // lock on 'Test.class' referencesynchronizedvoid test2() {} // lock on 'this' reference
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        args.notify(); // produces IllegalMonitorStateException
    }
}
пример
Given the following,
class Test {
    publicstaticvoid main(String [] args) {
        printAll(args);
    }

    publicstaticvoid printAll(String[] lines) {
        for(int i=0;i<lines.length;i++){
            System.out.println(lines[i]);
	        Thread.currentThread().sleep(1000);
 	    } 	 
    } 	 
} 	 
What is the result of this code?
        
A. Each String in the array lines will output, with a 1-second pause. 	 
B. Each String in the array lines will output, with no pause in between because this method is 	 
not executed in a Thread. 	 
C. Each String in the array lines will output, and there is no guarantee there will be a pause 	 
because currentThread() may not retrieve this thread. 	 
D. This code will not compile.
ответ
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        Object o = null;
        synchronized (o) { // throws NullPointerException
            System.out.println("test");
        }
    }
}

Подготовка к SCJP 1.5

Exam objectives

Var-args methods

пример
        void test1(Object...args) {}
void test2(Object      ...args) {}
void test3(Object...      args) {}
void test4(Object      ...      args) {}
пример
        void test1(int i, Object...args) {} // OKvoid test2(Object...args, int i) {} // compilation fails
пример
        void test(int... i, float... f) {} // compilation fails, too many var-arg parameters

Enums

пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        enum Number {ONE, TWO}; // compilation fails
    }
}
пример
        class Outer {
    privateclass Inner {
        enum Color {BLACK, WHITE}; // Compilation fails
    }
}
пример
        public
        class StartClass {
    
    enum Number {ONE, TWO}; // OKenum AnotherNumber {THREE, FOUR} // OK
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        System.out.println("BIG=" + Size.BIG.getSize() + ", SMALL=" + Size.SMALL.getSize());
    }
}

enum Size {
    BIG(10), SMALL(1);

    privateint size;

    Size(int size) {
        this.size = size;
    }
    publicint getSize() {
        return size;
    }
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        Size size = new Size(5); // compilation fails
    }
}

enum Size {
    BIG(10), SMALL(1);

    privateint size;

    Size(int size) {
        this.size = size;
    }

    publicint getSize() {
        return size;
    }
}
пример
        public
        class StartClass {

    privatestatic Size size;

    publicstaticvoid main(String[] args) {
        System.out.println("BIG=" + size.BIG.getSize() + ", SMALL=" + size.SMALL.getSize()); // OK
    }
}

enum Size {
    BIG(10), SMALL(1);

    privateint size;

    Size(int size) {
        this.size = size;
    }

    publicint getSize() {
        return size;
    }
}
пример
        public
        class StartClass {

    publicstaticvoid main(String[] args) {
        System.out.println(Size.BIG); // prints 'Ordinary size'
        System.out.println(Size.MEDIUM); // prints 'Ordinary size'
        System.out.println(Size.SMALL); // prints 'Really small'
    }
}

enum Size {
    BIG,
    MEDIUM,
    SMALL {
        public String toString() {
            return"Really small";
        }
    };

    public String toString() {
        return"Ordinary size";
    }
}
пример
        enum Test1 {
    FIRST, SECOND;
    privatestaticint test = 1;

    privateint i = test; // Compilation fails
}

enum Test2 {
    FIRST, SECOND;
    privatestaticint test = 1;

    {
        System.out.println(test); // Compilation fails
    } 
}

enum Test3 {
    FIRST, SECOND;
    privatestaticint test = 1;

    Test3() {
        System.out.println(test); // Compilation fails
    }
}
пример
        public
        class StartClass {

    enum Size {BIG, SMALL};

    publicstaticvoid main(String[] args) {
        Size size = Size.BIG;
        switch (size) {
            case BIG:
                System.out.println("Really big");
        }
    }
}
пример
        public
        class StartClass {

    enum Size {BIG, SMALL};

    publicstaticvoid main(String[] args) {
        Size size = Size.BIG;
        switch (size) {
            case Size.BIG: // Compilation fails
                System.out.println("Really big");
        }
    }
}

Covariant returns

пример
        class Base {
    public Object test() {
        returnnew Object();
    }
}

class Sub extends Base {

    public Sub test() { // OK because Sub IS-A Objectreturnthis;
    }
}

Coupling and cohesion

SCJP 1.5 требует знания терминов coupling и cohesion и, соответственно, понимания, почему именно low coupling и high cohesion есть хорошо. На всякий случай привожу ссылки на эти определения в википедии:

Autoboxing / autounboxing

функция
        static
        void doStuff(int x) {
    System.out.println(x);
}

Ответ - можно, потому что при autounboxing компилятор генерирует за нас дополнительный код. Например, если мы пишем

Integer i1 = new Integer(100);
int i2 = i1;

то этот код на самом деле эквивалентен следующему:

Integer i1 = new Integer(100);
int i2 = i1.intValue();

возвращаясь к первоначальному примеру, NullPointerException может возникнуть, например, так:

пример
        public
        class StartClass {

    static Integer i;

    publicstaticvoid main(String[] args) {
        doStuff(i); // исключение возбуждается, потому что на самом деле здесь doStuff(i.intValue()), а i = null
    }

    staticvoid doStuff(int x) {
        System.out.println(x);
    }
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        Integer i1 = 1000; // преобразовывается в Integer i1 = Integer.valueOf(1000);
        Integer i2 = 1000; // преобразовывается в Integer i2 = Integer.valueOf(1000);
        System.out.println(i1 == i2);
        System.out.println(i1 == 1000);
    }
}
ответ

С целью не потерять обратную совместимость с предыдущими версиями джавы при первом сравнении проверяется, ссылаются ли i1 и i2 на один и тот же объект. Не ссылаются. Второе же сравнение не вызовет ошибку компиляции только начиная с java 1.5, поэтому для этого случая (один операнд примитив, ко второму может быть применен autounboxing) возможно было реализовать сравнение действительных значений.

пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        Integer i1 = 10;
        Integer i2 = 10;
        System.out.println(i1 == i2);
        System.out.println(i1 == 10);
    }
}
ответ

Здесь сравнение i1 с i2 дает положительный результат, потому что при autoboxing в случае, когда соотвествующее значение примитивного типа принадлежит определенному интервалу, для одинаковых примитивных значений возвращается один и тот же объект. 10 – число из этого интервала, поэтому при autoboxing ссылки i1 и i2 связываются с одним и тем же объектом Integer. Такой эффект происходит при autoboxing Boolean, autoboxing Byte, Short, Integer, Long для значений из [-128; 127], autoboxing Character для значений из [‘\u0000’; ‘\u007F’]. На Double и Float это не распространяется, поэтому, например, следующий код напечатает false:

пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        Double d1 = 1d;
        Double d2 = 1d;
        System.out.println(d1 == d2);
    }
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        byte b = 1;
        test(b); // compilation fails because b is not allowed to wide from byte to long and then make autoboxing
    }
    
    privatestaticvoid test(Long var) {
    }
}

Т.к. здесь b не может быть неявно расширина, происходит autoboxing (byte -> Byte), потом проверяется, может ли переменная типа Byte использоваться как переменная типа Long (т.е. проверяется, верно ли, что Byte IS-A Long). Ответ нет, поэтому получаем ошибку компиляции;

пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        byte b = 1;
        test(b); // OK because Byte IS-A Object
    }

    privatestaticvoid test(Object var) {
    }
}
пример
        switch (new Integer(4)) {
    case 4:
        System.out.println("boxing is OK");
}
пример
        final Integer i = 1;
switch (1) {
    case i: // compilation fails
        System.out.println("unboxing is OK");
}

Overloading rules

пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        int i = 1;
        test(i); // prints 'test(long)'
    }

    privatestaticvoid test(Integer i) {
        System.out.println("test(Integer)");
    }

    privatestaticvoid test(long var) {
        System.out.println("test(long)");
    }
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        byte b = 1;
        test(b, b); // prints 'test(int, int)'
    }

    privatestaticvoid test(int x, int y) {
        System.out.println("test(int, int)");
    }

    privatestaticvoid test(byte ... b) {
        System.out.println("test(byte ...)");
    }
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        byte b = 1;
        test(b, b); // prints 'test(Byte, Byte)'
    }

    privatestaticvoid test(Byte x, Byte y) {
        System.out.println("test(Byte, Byte)");
    }

    privatestaticvoid test(byte ... b) {
        System.out.println("test(byte ...)");
    }
}

Static import

пример
        import
        static java.lang.Math.*;

publicclass StartClass {
    publicstaticvoid main(String[] args) {
        System.out.println(max(1, 2)); // calls java.lang.Math.abs(int, int)
    }
}
пример
        import
        static java.lang.Integer.*;
importstatic java.lang.Long.*;

publicclass StartClass {
    publicstaticvoid main(String[] args) {
        System.out.println(MAX_VALUE); // Compilation fails: both Integer.MAX_VALUE and Long.MAX_VALUE matches
    }
}

Bitwise operators

Enchanced for loop (for-each)

пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        List<String> list = new ArrayList<String>(); // List<E> extends Collection<E> & Collection<E> extends Iterable<E>
        list.add("a");
        list.add("b");
        for (String s : list) { // Compilation successful
            System.out.print(s + " "); // prints 'a b '
        }
        System.out.println("");

        MyIterable iterable = new MyIterable();
        for (Integer i : iterable) { // Compilation successful
            System.out.print(i + " "); // prints '0 1 2 '
        }
    }
}

class MyIterable implements Iterable<Integer> {

    privatestaticclass MyIterator implements Iterator<Integer> {

        privateint counter = -1;

        publicboolean hasNext() {
            return ++counter < 3;
        }

        public Integer next() {
            return counter;
        }

        publicvoid remove() {
        }
    }

    public Iterator<Integer> iterator() {
        returnnew MyIterator();
    }
}
пример
        int[] array = {1, 2};
int x;
for (x : array) { // compilation fails
    System.out.println(x);
}
пример
        int[] array1 = {1, 2};
for (long x : array1) { // compilation successfully
    System.out.println(x);
}

long[] array2 = {3, 4};
for (int x : array2) { // compilation failes: 'possible loss of precision'
    System.out.println(x);
}

Compiling assertion-aware code

StringBuilder class

пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        StringBuilder builder1 = new StringBuilder("test");
        StringBuilder builder2 = new StringBuilder("test");
        System.out.println(builder1.equals(builder2)); // prints false
    }
}

File navigation and I/O

File
File(File, String)
File(String)
File(String, String)
createNewFile()
delete()
exists()
isDirectory()
isFile()
list()
mkdir()
renameTo()
FileReader
FileReader(File)
FileReader(String)
read()
BufferedReader
BufferedReader(Reader)
read()
readLine()
FileWriter
FileWriter(File)
FileWriter(String)
close()
flush()
write()
BufferedWriter
BufferedWriter(Writer)
close()
flush()
newLine()
write()
PrintWriter
PrintWriter(File)
PrintWriter(String)
PrintWriter(OutputStream)
PrintWriter(Writer)
close()
flush()
format()
printf()
print()
println()
write()
СОВЕТ

Методы PrintWriter не пробрасывают IOException. Узнать, не произошла ли ошибка, можно только вызвав на нем метод checkError(). Поэтому (мое субъективное мнение) использовать его не стоит, достаточно BufferedWriter.

пример вопроса на эту тему
Given that bw is a reference to a valid BufferedWriter and the snippet:

15.  BufferedWriter b1 = new BufferedWriter(new File("f"));
16.  BufferedWriter b2 = new BufferedWriter(new FileWriter("f1"));
17.  BufferedWriter b3 = new BufferedWriter(new PrintWriter("f2"));
18.  BufferedWriter b4 = new BufferedWriter(new BufferedWriter(bw));

What is the result?

A. Compilation succeeds.
B. Compilation fails due only to an error on line 15.
C. Compilation fails due only to an error on line 16.
D. Compilation fails due only to an error on line 17.
E. Compilation fails due only to an error on line 18.
F. Compilation fails due to errors on multiple lines.
ответ
создание файла
        public
        class StartClass {
    publicstaticvoid main(String[] args) throws IOException {
        FileOutputStream fOut = new FileOutputStream(new File("abcdefg.txt"));
        fOut.close();
    }
}

Но это правило не распространяется на создание новых каталогов:

пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) throws IOException {
        File myDir = new File("mydir");
        File myFile = new File(myDir, "myfile.txt");
        FileWriter writer = new FileWriter(myFile); // FileNotFoundException: mydir\myfile.txt (The system cannot find the path specified)
        writer.close();
    }
}
пример
        public
        class StartClass {
      publicstaticvoid main(String [] args) throws IOException {
          FileReader reader = new FileReader(new File("abcdefg.txt")); // java.io.FileNotFoundException: abcdefg.txt (The system cannot find the file specified)
      }
}
пример
        public
        class StartClass {
      publicstaticvoid main(String [] args) throws IOException {
          File dir = new File("mydir"); // assuming that no such dir exists
          File file = new File(dir, "myFile");
          file.createNewFile(); // java.io.IOException: The system cannot find the path specified
      } 
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) throws IOException {
        File myDir = new File("mydir");
        myDir.mkdir();
        File myFile = new File(myDir, "myfile.txt");
        myFile.createNewFile();
        System.out.println(myDir.delete()); // prints false
        myFile.delete();
        System.out.println(myDir.delete()); // prints true
    }
}
константы
File.separatorChar
File.separator
File.pathSeparatorChar
File.pathSeparator

Serialization

пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) throws IOException {
        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
        ObjectOutputStream oOut = new ObjectOutputStream(bOut);
        Whole object = new Whole();
        oOut.writeObject(object); //java.io.NotSerializableException: Part
    }
}

class Whole implements Serializable {
    privatefinal Part part = new Part();
}

class Part {
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) throws Exception {
        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
        ObjectOutputStream oOut = new ObjectOutputStream(bOut);
        Whole object = new Whole();
        oOut.writeObject(object);
    }
}
class Whole implements Serializable {
    publicvoid writeObject(ObjectOutputStream out) {
        System.out.println("Whole.writeObjet()"); // is never called since method is public
    }
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) throws Exception {
        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
        ObjectOutputStream oOut = new ObjectOutputStream(bOut);
        oOut.writeObject(new Whole());

        ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
        ObjectInputStream oIn = new ObjectInputStream(bIn);
        oIn.readObject(); //java.io.StreamCorruptedException
    }
}
class Whole implements Serializable {

    transient Part part = new Part(1);
    int wholePart;

    privatevoid writeObject(ObjectOutputStream out) throws IOException {
        out.writeInt(part.partField);
        out.defaultWriteObject();
    }

    privatevoid readObject(ObjectInputStream in) throws Exception {
        // lines (1) and (2) must be changedin.defaultReadObject(); // (1)
        part = new Part(in.readInt()); // (2)
    }
}

class Part {
    int partField;

    public Part(int field) {
        this.partField = field;
    }
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) throws Exception {
        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
        ObjectOutputStream oOut = new ObjectOutputStream(bOut);
        oOut.writeObject(new Sub()); // prints '1 Base.Base() 2 Sub.Sub()'

        System.out.println("");
        ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
        ObjectInputStream oIn = new ObjectInputStream(bIn);
        oIn.readObject(); // prints '1 Base.Base()'
    }
}
class Base {

    privateint baseField = getInt(1);

    public Base() {
        System.out.print("Base.Base() ");
    }

    protectedint getInt(int i) {
        System.out.print(i + " ");
        return i;
    }
}

class Sub extends Base implements Serializable {
    
    privateint subField = getInt(2);

    public Sub() {
        System.out.print("Sub.Sub() ");
    }
}

Dates, Numbers and Currency

классы
java.util.Date
java.util.Calendar
java.text.DateFormat
java.text.NumberFormat
java.util.Locale
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) throws Exception {
        Date date = new Date(1000000000000L);
        System.out.println(date); // (1) prints 'Sun Sep 09 05:46:40 MSD 2001'

        DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.LONG);
        String dateRepresentation = dateFormat.format(date);
        System.out.println(dateRepresentation); // prints '9 Сентябрь 2001 г.'

        Date newDate = dateFormat.parse(dateRepresentation);
        System.out.println(newDate); // prints 'Sun Sep 09 00:00:00 MSD 2001'. Compare with (1)
    }
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) throws Exception {
        float f = 123.45678f;
        NumberFormat numberFormat = NumberFormat.getInstance();
        numberFormat.setMaximumFractionDigits(2);
        System.out.println(numberFormat.format(f)); // prints '123,46'
    }
}

Parsing, Tokenizing and Formatting

классы
java.util.regex.Pattern
java.util.regex.Matcher
java.lang.String
java.util.Scanner
java.util.Formatter
пример на использование регулярных выражений
Given:
publicclass StartClass {
    publicstaticvoid main(String[] args) throws Exception {
        String source = "ab34ef";
        String regex = "\\d*";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(source);
        while (m.find()) {
            System.out.print(m.start() + m.group());
        }

    }
}
What is the result?
A. 234 
B. 334 
C. 334 
D. 0123456 
E. 01234456 
F. 12334567 
G. Compilation fails.
ответ
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) throws Exception {
        String source = "a 3 bc 23 d";
        Scanner scanner = new Scanner(source);
        scanner.useDelimiter("\\d");
        while (scanner.hasNext()) {
            System.out.println(">" + scanner.next() + "<");
        }
    }
}
результат

Тот же результат мы получим и, например, если будем использовать String.split():

пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        String source = "a 3 bc 23 d";
        String[] tokens = source.split("\\d");
        for (String token : tokens) {
            System.out.println(">" + token + "<");
        }
    }
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        System.out.printf("%b\n", 1.2); // prints 'true'
        System.out.printf("%b", new Object()); // prints 'true'
    }
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        System.out.printf("%c", "c"); // java.util.IllegalFormatConversionException: c != java.lang.String
    }
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        System.out.printf("%s\n", 1); // prints '1'
        System.out.printf("%s\n", 2.3); // prints '2.3'
        System.out.printf("%s\n", true); // prints 'true'
        System.out.printf("%s", new Test()); // prints 'Test.toString()'
    }
}

class Test {
    public String toString() {
        return"Test.toString()";
    }
}

Generics

пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        ArrayList<Base> list = new ArrayList<Sub>(); // Compilation fails
    }
}

class Base {
}

class Sub extends Base {
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        Set<List<String>> set1 = new HashSet<List<String>>(); // OK
        Set<List<String>> set2 = new HashSet<ArrayList<String>>(); // Compilation fails
    }
}
пример
        class Test {
    void test(List<Integer> list) { // Compilation fails
    }

    void test(List<String> list) { // Compilation fails
    }
}
пример
        class Test {
    void test1(List<? extends Serializable> list) { // OK
    }
    
    void test2(Set<? implements Serializable> set) { // Compilation fails
    }
}
пример
        class Test {

    <T extendslong> void test1(T t) { // Compilation fails
    }

    <T extends Object[]> void test2(T t) { // Compilation fails
    }
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        List<?> list1 = new ArrayList<? extends Object>(); // Compilation fails
        List<?> list2 = new ArrayList<?>(); // Compilation fails
    }
}

Из этого следует, например, что следующая попытка создать копию списка не скомпилируется:

invalid copying
        class Test {
    void testInvalidCopy(List<?> list) {
        List<?> copy = new ArrayList<?>(list); // Compilation fails
    }
}

Надо делать так:

valid copying
пример
        class Test {
    public <T> Test(T t) {
    }
}
пример
        class T {
    public <T> T(T t) { // t's type is constructor's type parameter, not T.class
    }
}
пример
        class Test<?> { // Compilation fails
}

class MyList extends ArrayList<?> { // Compilation fails
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        List<?> list = new ArrayList<String>();
        list.add("a"); // Compilation fails
        list.add(null); // OK

        Test<?> testObject = new Test<Integer>();
        testObject.test(1); // Compilation fails
        testObject.test(null); // OK
    }
}

class Test<T> {
    void test(T t) {
    }
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        List<?> list = new ArrayList<String>();
        String firstElement = list.get(0); // Compilation fails
        Object secondElement = list.get(1); // OK

        Test<?> testObject = new Test<Integer>();
        Integer var1 = testObject.get(); // Compilation fails
        Object var2 = testObject.get(); // OK
    }
}

class Test<T> {
    T get() {
        returnnull;
    }
}
пример
        class Test {
    <T> void method1(T t) { // OK
    }
    
    void <T> method2(T t) { // Compilation fails
    }
}
пример
        class ObjectStore<T extends Comparable<T> & Comparable<String>> { // Compilation fails   
}
пример
        class Base {
    publicvoid test() {
    }
}

class Sub extends Base {
    public <T> void test() { // Compilation fails
    }
}
пример
        class Test<T> {
    staticvoid method(T t) { // Compilation fails
    }
}
пример
        enum Color<T> { // Compilation fails
    WHITE, BLACK
}
пример
        enum Shape {
    TRIANGLE, SQUARE;

    public <T> T test(T t) { // OKreturn t;
    }
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        test1(new ArrayList<String>());
        test2(new ArrayList<String>());
    }

    privatestaticvoid test1(List<?> list) {
        System.out.println(list instanceof LinkedList<String>); // Compilation fails
    }
    
    privatestaticvoid test2(List<?> list) {
        System.out.println(list instanceof LinkedList); // OK
    }
}
пример
        class Test<T> {
    void test(T t) {
        Object array1 = new T[5]; // ?The component type of an array object may not be a type variable
        T[] array2 = {t}; // Even agregate initialization is not allowed
        Class<T>[] array3 = new Class<T>[5]; // ?The component type of an array object may not be parameterized type
    }
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        List<?>[] array = new List<?>[2]; //OK
        List<Integer> list1 = new ArrayList<Integer>();
        list1.add(1);
        List<String> list2 = new ArrayList<String>();
        list2.add("2");
        array[0] = list1; // OK
        array[1] = list2; // OK
        Integer i = (Integer) array[0].get(0); // OK but explicit case is necessary
        String s = (String) array[1].get(0); // OK but explicit case is necessary
    }
}
пример
        public
        class StartClass {
    publicstaticvoid main(String[] args) {
        String s = test("test"); // OK
        Integer i1 = <Integer>test(1); // Compilation fails
        Integer i2 = StartClass.<Integer>test(1); // OK
    }

    privatestatic <T> T test(T t) {
        return t;
    }
}
пример
        public
        class TestClass {
    private <T extends Interface1 & Interface2> void test1(T t) { // OK
    }
    
    private <T extends Class1 & Interface1 & Interface2> void test2(T t) { // OK
    }

    private <T extends Interface1 & Class1> void test3(T t) { // Compilation fails
    }
}

interface Interface1 {
}

interface Interface2 {
}

class Class1 {
}

class Class2 {
}
пример
        class MyException<T> extends Exception { // Compilation fails
}
пример
        class TestClass {
    <T extends Exception> void test(T t) throws T {
        throw t;
    }
}
пример
        class TestClass {
    <T extends Exception> void test(T t) {
        try {
        } catch (T e) {
        }
    }
}

Collections changes

Материалы


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