Archiwa kategorii: Zdaj OCPJP

Zdaj OCPJP – pytanie 50

Jaki będzie efekt działania poniższego fragmentu kodu?

package eu.javablog.parameters;

public class ParametersTest {

	public void testParam(int param) {
		System.out.println("int");
	}
	
	public void testParam(Integer param) {
		System.out.println("Integer");
	}
	
	public void testParam(int... param) {
		System.out.println("int...");
	}
	
	public void testParam(Number param) {
		System.out.println("Number");
	}
	
	public static void main(String[] args) {
		short primitive = 1;
		Short wrapper = 1;
		ParametersTest test = new ParametersTest();
		test.testParam(primitive);
		test.testParam(wrapper);
	}
}

 

  1. Wyświetlone zostanie int oraz Number.
  2. Wyświetlone zostanie int oraz int.
  3. Wyświetlone zostanie Number oraz Number.
  4. Wyświetlone zostanie int oraz int….
  5. Program nie skompiluje się.
  6. Rzucony zostanie wyjątek w trakcie działania programu.

 

Pokaż odpowiedź »

Poprawna jest odpowiedź nr 1.
Aby poprawnie odpowiedzieć na to pytanie należy znać reguły, według których wybierane są metody o różnych sygnaturach. Są one dość proste i opierają się na kilku głównych punktach:

  1. jeżeli istnieją metody, które przyjmują parametry typów prostych, które są większe niż parametr wejściowy, to wybierana jest metoda o najmniejszym z nich (widening). Przykład:
    short p = 1;
    void test(int in) { ... }
    void test(long in) { ... }
    

    Wybrana zostanie metoda void test(int in) { … }.

  2. typy proste mogą być wykorzystane w metodach przyjmujących typy opakowujące (autoboxing). Przykład:
    short p = 1;
    void test(Short in) { ... }
    // test(p) is legal
    
  3. nie możemy liczyć na automatyczne dostosowywanie się typów opakowujących (widening). Przykład:
    Short p = 1;
    void test(Integer in) { ... }
    // test(p) is illegal, cannot convert from Short to Integer
    
  4. konwersja z typów prostych na typy opakowujące nie może być łączona z automatycznym dostosowywaniem się typów opakowujących (widening). Przykład:
    short p = 1;
    void test(Integer in) { ... }
    // test(p) is illegal, cannot convert from short to int and then box to Integer
    
  5. autoboxing, po którym następuje rozszerzanie typu jest w pełni dopuszczalny. Przykład:
    short p = 1;
    void test(Number in) { ... }
    // test(p) is legal
    
  6. zmienne listy argumentów mają najmniejszy priorytet i mogą być łączone z automatycznym wybieraniem docelowego typu oraz autoboxingiem.

Zdaj OCPJP – pytanie 49

Co będzie efektem kompilacji i uruchomienia poniższego kodu?

interface I
{
    void print();
}

abstract class A implements I
{

}

class B extends A
{
    void print()
    {
        System.out.println("CLASS B");
    }
}

public class Sample
{
    public static void main(String[] args)
    {
        B b = new B();
        b.print();
        System.out.println(b instanceof I);
    }
}

 

  1. Wydrukowane zostanie odpowiednio CLASS Btrue.
  2. Wystąpi błąd kompilacji w linii 6.
  3. W trakcie działania aplikacji rzucony zostanie wyjątek.
  4. Wydrukowane zostanie odpowiednio CLASS Bfalse.
  5. Wystąpi błąd kompilacji w linii 13.

 

Pokaż odpowiedź »

Poprawna jest odpowiedź nr 5.

Kompilacja nie powiedzie się, ponieważ nie można przesłonić metody wersją o bardziej restrykcyjnym poziomie dostępu. Metody interfejsu domyślnie są publiczne, więc przesłonić można je jedynie publiczną metodą. Błędu kompilacji nie spowoduje natomiast brak implementacji metody print w abstrakcyjnej klasie A. Dopóki klasa jest abstrakcyjna, nie musi ona implementować abstrakcyjnych metod pochodzących z interfejsów i abstrakcyjnych nadklas.

Zdaj OCPJP – pytanie 48

Jaki będzie efekt uruchomienia poniższego kodu?

package eu.javablog.clonetest;

import java.util.List;

public class Dolly {
	private int lenght = 1; 
	private int weight = 15;
	
	public static void main(String... args) throws CloneNotSupportedException {
		List<Dolly> originals = new ArrayList<Dolly>();
		originals.add(new Dolly());
		
		List<Dolly> clones = (List<Dolly>)originals.clone();
                
        // modifies first animal
		clones.get(0).weight = 0;
		
        System.out.println("clone: " + clones.get(0).lenght + " " + clones.get(0).weight);
        System.out.println("original: " + originals.get(0).lenght + " " + originals.get(0).weight);
	}	
}

 

  1. Kod nie skompiluje się.
  2. Rzucony zostanie wyjątek w linii 13.
  3. Wydrukowane zostaną te same wartości dla listy oryginalnej oraz sklonowanej.
  4. Wydrukowane różne wartości dla listy oryginalnej oraz sklonowanej.

 

Pokaż odpowiedź »

Prawidłowa jest odpowiedź nr 1.

Interfejs List nie posiada publicznej metody clone. Metoda clone jest co prawda zdefiniowana jako jedna z metod klasy Object, ale jest ona oznaczona jako protected i aby stała się widoczna wymaga przeciążenia w klasach pochodnych. Co ciekawe, klasa ArrayList posiada własną implementację metody clone, która kopiuje jedynie samą listę, zachowując oryginalne referencje do składowanych obiektów.

Zdaj OCPJP – pytanie 47

Co będzie efektem kompilacji i uruchomienia kodu znajdujących się w poniższych dwóch plikach?

package eu.javablog.ocpjp;

import eu.javablog.ocpjp.other.SecondSample;

class SubSample extends SecondSample
{
    public String toString()
    {
        return "SUB: " + i;
    }
}

public class Sample extends SubSample
{
    public void print()
    {
        SubSample sub = new SubSample();
        System.out.println(sub.i);
    }

    public static void main(String... args)
    {
        new Sample().print();
    }
}
package eu.javablog.ocpjp.other;

public class SecondSample
{
    protected Integer i = 100;

    public String toString()
    {
        return "SECOND:" + i;
    }
}

 

  1. Wydrukowane zostanie 100.
  2. Kod nie skompiluje się.
  3. Wydrukowane zostanie null.
  4. Wydrukowane zostanie 0.
  5. Kod uruchomi się, ale w trakcie działania zostanie rzucony wyjątek.

 

Pokaż odpowiedź »

Prawidłowa jest odpowiedź nr 2.

Udzielenie poprawnej odpowiedzi wymaga znajomości niuansów poziomu dostępu protected. Daje on dostęp innym klasom w obrębie pakietu, a także spoza niego poprzez dziedziczenie. Jeśli jednak klasa dziedzicząca znajduje się w innym pakiecie, odziedziczona zmienna zachowuje się dalej jak prywatna.

Zdaj OCPJP – pytanie 46

Jaki będzie efekt kompilacji i uruchomienia poniższego kodu?
Należy założyć, że niezbędne importy znajdują się na swoim miejscu.

class A implements Serializable
{
    private static final long serialVersionUID = 1L;

    public String text;

    public static String staticText;

    public String toString()
    {
        return text + " " + staticText;
    }
}

public class Sample
{
    public static void main(String... args) throws Exception
    {
        A a = new A();
        a.text = "TEXT";
        a.staticText = "STEXT";
        System.out.println(a);

        ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bytesOut);

        out.writeObject(a);
        byte[] bytes = bytesOut.toByteArray();
        ByteArrayInputStream bytesIn = new ByteArrayInputStream(bytes);
        ObjectInputStream in = new ObjectInputStream(bytesIn);

        a.staticText = "CHSTEXT";

        A deserialized = (A) in.readObject();
        System.out.println(deserialized);
    }
}

 

  1. Kod nie skompiluje się.
  2. Wydrukowane zostanie odpowiednio TEXT STEXT i TEXT STEXT.
  3. Kod skompiluje się, ale w trakcie działania rzucony zostanie wyjątek.
  4. Wydrukowane zostanie odpowiednio TEXT STEXT i TEXT CHSTEXT
  5. Wydrukowane zostanie odpowiednio TEXT STEXT i TEXT null.

 

Pokaż odpowiedź »

Poprawna jest odpowiedź nr 4.

Należy bezwzględnie pamiętać o tym, iż w procesie serializacji serializowane są instancje klasy, a nie sama klasa. Zmienne statyczne przynależą do klasy, nie zaś do poszczególnych obiektów. Ich wartości nie będą więc ani zapisywane, ani odczytywane podczas serializowania.

Zdaj OCPJP – co dalej?

Nasz kurs przygotowujący do egzaminu Oracle Certified Professional Java Programmer zbliża się ku końcowi. Postanowiliśmy zakończyć pierwszą edycję kursu na 50 pytaniach. Po dodaniu ostatniego pytania opublikujemy dokument PDF zawierający wszystkie dotychczasowe wpisy wraz z wyjaśnieniami. Co więcej, postanowiliśmy oddać w Wasze ręce interaktywny quiz, rozszerzony o szereg informacji przydatnych w czasie przygotowań do egzaminu. Będzie on dostępny dla posiadaczy tabletów z logo nadgryzionego jabłka bezpośrednio z poziomu iBookstore. Oczywiście tytuł ten będzie w pełni darmowy.

Co dalej? Rozpoczniemy kursy przygotowujące do dwóch kolejnych egzaminów – Oracle Certified Professional Enterprise JavaBeans Developer oraz Oracle Certified Professional Java Persistence API Developer. Zapoczątkujemy także serię wpisów spod szyldu „Java Hadcore”, traktującą o specyficznych mechanizmach spotykanych w Javowym ekosystemie. Idealny materiał dla ludzi znudzonych OCPJP.

A czy wspominaliśmy już, że zbliża się JARCamp? :)

Zdaj OCPJP – pytanie 45

Jaki będzie efekt uruchomienia poniższego kawałka kodu?

package eu.javablog.arrayaslist;

import java.util.Arrays;
import java.util.List;

public class AsListTest {

	public static void main(String[] args) {
		String[] testArray = {"test1", "test2", "test3"};
		List<String> testListFromArray = Arrays.asList(testArray);
		testListFromArray.add("test4");
		System.out.println(testArray[3]);
	}
}

 

  1. Kod się nie skompiluje.
  2. Zostanie rzucony wyjątek ArrayIndexOutOfBoundsException w linii 10.
  3. Zostanie rzucony wyjątek ArrayIndexOutOfBoundsException w linii 12.
  4. Wyświetlone zostanie ‚test4′.
  5. Żadna z odpowiedzi nie jest poprawna.

 

Pokaż odpowiedź »

Poprawna jest odpowiedź nr 5.
Podczas uruchomienia programu zostanie rzucony wyjątek typu UnsupportedOperationException w linii 11. Lista zwracana przez Arrays.asList(…) nie może być modyfikowana więc powyższy wyjątek zostanie rzucony przy okazji wykonania dowolnej z poniższych operacji:

  • add
  • remove
  • clear

Jeżeli przyjrzymy się dokładnie liście zwracanej przez wywołanie Arrays.asList():

public static void main(String[] args) {
	String[] testArray = {"test1", "test2", "test3"};
	List<String> testListFromArray = Arrays.asList(testArray);
	System.out.println(testListFromArray.getClass().getName());
}

to zobaczymy, że lista jest instancją wewnętrznej klasy java.util.Arrays$ArrayList a nie jednej z dobrze znanych i popularnych kolekcji.

Jeżeli chcemy stworzyć edytowalną listę to możemy przekazać rezultat wywołania Arrays.asList() do konstruktora np. ArrayListy:

String[] testArray = {"test1", "test2", "test3"};
List<String> testListFromArray = Arrays.asList(testArray);
List<String> editableList = new ArrayList<String>(testListFromArray);

Pytanie inspirowane wpisem Marka Needhama.

Zdaj OCPJP – pytanie 44

Poniżej przedstawiony jest kod źródłowy.

package eu.javablog.ocpjp;

public class Sample
{
    public static void main(String[] args)
    {
        for(String arg : args)
        {
            System.out.println(arg.toUpperCase());
        }
    }
}

Co będzie efektem kompilacji i uruchomienia go następującym poleceniem?

java eu.javablog.ocpjp.Sample

 

  1. Kod nie skompiluje się.
  2. W trakcie wykonania rzucony zostanie NullPointerException w linii 7.
  3. W trakcie wykonania rzucony zostanie NullPointerException w linii 9.
  4. Program zakończy się prawidłowo i nic nie zostanie wydrukowane.
  5. Wydrukowany zostanie tekst EU.JAVABLOG.OCPJP.SAMPLE.

 

Pokaż odpowiedź »

Poprawna jest odpowiedź nr 4.

Nie zostanie wydrukowane nic. Warto pamiętać o tym, że jeśli nie podamy żadnych parametrów przy uruchomieniu programu, do metody main przekazana zostanie pusta tablica, a nie null. Pierwszym elementem tejże tablicy będzie zawsze pierwszy przekazany argument, nie nazwa uruchamianej klasy.

Zdaj OCPJP – pytanie 43

Jaki będzie efekt skompilowania i uruchomienia przedstawionego poniżej kodu?

public class Sample
{
    public static void main(String[] args)
    {
        Runnable task = new Runnable()
        {
            @Override
            public void run()
            {
                try
                {
                    wait();
                    System.out.println("THREAD");
                }
                catch (InterruptedException e)
                {
                    // thread was interrupted
                }
            }
        };

        Thread t = new Thread(task);
        t.start();
        task.notify();
    }
}

 

  1. Kod nie skompiluje się.
  2. W trakcie działania aplikacji rzucony zostanie więcej niż jeden wyjątek.
  3. Wydrukowane zostanie THREAD.
  4. Nic nie zostanie wydrukowane.
  5. W trakcie działania aplikacji rzucony zostanie wyjątek.

 

Pokaż odpowiedź »

Prawidłowa jest odpowiedź nr 2.

W każdym z dwóch wątków powyższej aplikacji rzucony zostanie IllegalMonitorStateException. Powodem takiego zachowania jest fakt, iż metody wait() i notify() nie są wywoływane w synchronizowanym kontekście. Problem rozwiązać można np. przez umieszczenie wspomnianych wywołań w bloku synchronizowanym względem obiektu, na którym metody te są wykonywane. Alternatywnie, jeśli używany jest obiekt this, zsynchronizować można całą metodę. Poniżej znajduje się kompletny, poprawiony przykład:

public class Sample
{
    public static void main(String[] args)
    {
        Runnable task = new Runnable()
        {
            @Override
            public synchronized void run()
            {
                try
                {
                    wait();
                    System.out.println("THREAD");
                }
                catch (InterruptedException e)
                {
                    // thread was interrupted
                }
            }
        };

        Thread t = new Thread(task);
        t.start();

        synchronized (task)
        {
            task.notify();
        }
    }
}

Uwaga!

Poprzez rozwiązanie problemu rozumiane jest poprawne użycie metod wait i notify w synchronizowanym bloku, co zapobiega rzucaniu wyjątków. Poprawiony w ten sposób przykład może powodować wystąpienie zakleszczenia.

Zdaj OCPJP – pytanie 42

Co można powiedzieć o wydruku wygenerowanym przez poniższy program?

class Task extends Thread
{
    private static int i, j;

    @Override
    public void run()
    {
        while(true)
        {
            print();
        }
    }

    private synchronized void print()
    {
        i++;
        j++;
        System.out.println(i + " " + j);
    }
}

public class Sample
{
    public static void main(String[] args)
    {
        new Thread(new Task()).start();
        new Thread(new Task()).start();
    }
}

 

  1. Drukowane będą zawsze pary takich samych liczb.
  2. Kod skompiluje się, ale w trakcie działania rzucony zostanie wyjątek.
  3. Drukowane będą zawsze pary różnych liczb.
  4. Kod nie skompiluje się.
  5. Nie ma pewnych informacji odnośnie wydruków.

 

Pokaż odpowiedź »

Poprawna jest odpowiedź nr 5.

Pierwszym zabiegiem, który może wydać się niepoprawny, jest użycie klasy Thread tam, gdzie standardowo stosuje się interfejs Runnable. Trzeba jednak pamiętać, że klasa Thread implementuje rzeczony interfejs – nic nie stoi więc na przeszkodzie, by manewr taki zastosować. Drugą rzeczą jest synchronizowana metoda print, która sugeruje, że drukowane powinny być zawsze pary takich samych liczb. Po głębszej analizie widać jednak, iż dwa utworzone wątki mają zupełnie osobne instancje klasy Task. W każdej z nich metoda print synchronizowana wyłącznie w ramach obiektu, czego skutkiem jest brak możliwości podania pewnej informacji odnośnie wydruków aplikacji.