Strona główna > Java > Kilka pytań rekrutacyjnych

Kilka pytań rekrutacyjnych

Kilka ciekawych pytań sprawdzających znajomość javy.

StringBuffer vs. StringBuilder
Pytanie może wyglądać tak: jaka jest różnica pomiędzy StringBuffer, a StringBuilder? lub który z nich jest wydajniejszy?

Sprawdzane jest tutaj to czy wie się że StringBuilder jest młodszym bratem StringBuffer (wprowadzony w wersji 1.5) i że główna różnica pomiędzy nimi to brak słowa synchronized przy publicznych metodach w przypadku StringBuilder. Pośrednio z tej wiedzy wynika także odpowiedź na pytanie o wydajności.

Patrząc pobieżnie na projekty w których pracowałem i kod który został użyty do klejenia stringów, to widzę że przewaga jest po stronie StringBuffer😉. Jest tak raczej z przyzwyczajenia, po za tym operacje te nie są krytyczne i jest ich nie wiele. Mam jednak postanowienie na przyszłość: jak powołuje do życia obiekt klasy do klejenia stringów, i ten obiekt zakończy swój żywot w obrębie tego samego bloku kodu (ciała metody) to używać należy StringBuilder, przykład:

  public static String getCustomStackTrace(Throwable aThrowable) {
    final StringBuilder result = new StringBuilder( "StackTrace: " );
    result.append(aThrowable.toString());
    final String NEW_LINE = System.getProperty("line.separator");
    result.append(NEW_LINE);

    //add each element of the stack trace
    for (StackTraceElement element : aThrowable.getStackTrace() ){
      result.append( element );
      result.append( NEW_LINE );
    }
    return result.toString();
  }

Reprezentacja pieniędzy
Pytanie może wyglądać tak: czego byś użył do reprezentacji pieniędzy (np. należności za zamówienie)?. Dalsza wersja tego pytania może być uzasadnienie podanej odpowiedzi.

Mi od razu nasuwa się BigDecimal, jako że od zawsze tego używałem. Robiłem to nie z powodu jakichś głębszych przemyśleń, ale z przyzwyczajenia, że tak powinno być. Jeśli kiedyś znałem jakieś uzasadnienie tego, to ugrzęzło ono w odmentach pamięci😉. Tak też powiedzenie na przykład dlaczego nie float wprowadziło mnie w lekkie zakłopotanie.
Szukając trochę, znalazłem że proste typy numeryczne nie gwarantują poprawności co do oczekiwanego wyniku na operacjach z liczbami zmiennoprzecinkowymi.
Prosty przykład:

		double badValue = 0.33;
		System.out.println(10*badValue);
		
		BigDecimal goodValue = new BigDecimal("0.33");
		System.out.println(goodValue.multiply(BigDecimal.TEN));

I wyniki są następujące:

3.3000000000000003
3.30

Co ciekawe jeśli zainicjujemy BigDecimal trochę inaczej (nie jako string, ale przekazując prosty typ):

		BigDecimal goodValue = new BigDecimal(0.33);
		System.out.println(goodValue.multiply(BigDecimal.TEN));

to możemy otrzymać coś takiego:

3.300000000000000155431223447521915659308433532714843750

Więc i tu też może być haczyk😉. Ale główna wiedza jaka jest sprawdzana przez takie pytanie to świadomość o możliwości utracie precyzji przy wykorzystaniu prostych typów (tutaj też znalazłem fajne streszczenie tego).

Działanie equals() i hashCode()
Pytania tutaj mogą być przeróżna, ale ich cel to sprawdzenie czy ktoś rozumie po co są te metody i jak je używać.

Jak dla mnie pierwsze ze skojarzeń jakie mam z tym to pamiętanie o tym aby zaimplementować je w tworzonej klasie jeśli chce się przechowywać obiekty tej klasy w kolekcjach. Wiedząc o tym, przy tworzeniu nowej klasy, uruchamiamy odpowiedni skrót w IDE i otrzymuję wygenerowane metody. I na tym może się kończyć nasz refleksja nad sensem tych metod, co też może prowadzić do zdziwień w przykładach jak poniżej.

Załóżmy, że mamy klasę, w których implementacja tych metod są takie że: equals zwraca zawsze false, a hashCode zawsze 1 (to budzi lekkie zdziwienie po co tworzyć takie coś, ja sam nie znajduję sensownej przyczyny robienia czegoś takiego ;)). Idźmy dalej: powiedzmy że klasa ta to Person i w konstruktorze przyjmuję pojedynczą wartość String, będącą nazwą danej osoby.
Tak więc tworzymy trzy instancje tej klasy dwie z argumentem „Jan”, jednak z „Tomasz” i dodajemy jej do kolekcji typu HashSet. Pytanie jest, ile obiektów jest w kolekcji?.
Jest to pytanie na zrozumienie zasad stosowania tych dwóch metod. Wiedza ta jest tu sprawdzana trochę w zagmatwany sposób. Tym się usprawiedliwiam🙂, bo gdy usłyszałem to pytanie w takiej postaci udzieliłem złej odpowiedzi. Wychodząc z założenia, że w kolekcjach typu Set nie może być duplikatów, twierdziłem że będzie tylko jeden „Jan” w towarzystwie „Tomasz”. Ignorując zupełnie fakt, że nadpisałem metodę equals, które mówi mi o tym czy dany obiekt znajduję się już w kolekcji. Zakładając bez większego zastanowienia że słówka hash w HashSet gra tu istotną role i próbowałem strzelać co do odpowiedzi bez większego namysłu. Podczas gdy hashCode zadecyduje tylko o rozkładzie w „kubełkach” tej kolekcji (a właściwie tylko w jednym „kubełku” co zapewniliśmy sobie pisząc w taki sposób metodę hashCode), a equels zadecyduję i tak czy dany obiekt jest duplikatem.
Kończę usprawiedliwianie swojej pomyłki: podane przykład powinien mieć pomocnicze pytanie (lub samemu powinno się je zadać sobie): dlaczego taka implementacja equals i hashCode jest błędna?

Kategorie:Java Tags:
  1. Brak komentarzy.
  1. No trackbacks yet.

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Log Out / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Log Out / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s

%d bloggers like this: