Blaski i cienie rekrutacji do firmy informatycznej

Filmy mówiące o procesie rekrutacji do firmy informatycznej.

Tags: , ,

Wielokrotne rzutowanie typów prostych

Poniżej znajduje się prosta aplikacja, która rzutuje jedną liczbę między różnymi typami, tak że na wejściu mamy typ int, na wyjściu także.

1
2
3
4
5
public class Multicast {
    public static void main(String[] args) {
        System.out.println((int) (char) (byte) -1);
    }
}

I pytanie, co zostanie wydrukowane?.

Program jest dosyć prosty. Konwersja rozpoczyna się od cyfry -1, będącej typu int (domyślny typ dla liczb całkowitych). Następnie zostaje dokonana konwersja zawężająca do typu byte (8 bitów), potem do char (16 bitów) a na końcu z powrotem do typu int (32 bity). A na końcu drukuje liczbę 65535. I teraz pytanie brzmi, dlaczego nie -1?

Java wykorzystuje do prowadzenia obliczeń tzw. kod uzupełnień do dwóch:

Kod uzupełnień do dwóch (w skrócie U2 lub ZU2) – system reprezentacji liczb całkowitych w dwójkowym systemie pozycyjnym. Jest obecnie najpopularniejszym sposobem zapisu liczb całkowitych w systemach cyfrowych. Jego popularność wynika z faktu, że operacje dodawania i odejmowania są w nim wykonywane tak samo jak dla liczb binarnych bez znaku.

Z tej reprezentacji wynika, że liczba -1 w reprezentacji dwójkowej składa się z 32 jedynek. Rzutowanie z typu int to typu byte jest prosta i nie sprawia problemów. W wyniku tej konwersji zostają usunięte wszystkie bity oprócz tych najmniej znaczących. Czyli koniec końców także otrzymujemy liczbę -1 zapisane w 8 bitach (8 jedynek).

Natomiast rzutowanie na tym char sprawia więcej problemów. Typ char jest typem, w kŧórym można zapisać tylko liczby dodatnie, więc nie można zapisać w nim wartości ujemnej. Z tego powodu konwersja z typu char do byte nie jest uważana za konwersję rozszerzającą, tylko jest konwersja zawężająca. To powoduje, że najpierw nasŧępuje niejawna konwersja do typu int a dopiero teraz do typu char.

Więc najpierw następuje konwersja z typu byte na int, co powoduje, że uzyskujemy liczbę -1, która w zapisie dwójkowym składa się z 32 jedynek. Następnie dokonana zostaje konwersja do typu char, czyli zostają zachowane najmniej znaczące 16 bitów, czyli same jedynki czyli 65535.

Źródła

Tags: ,

Konwersja typów prymitywnych

W Javie można rozróżnić kilka typów prymitywnych. Każdy z tych typów charakteryzuje się pewnymi właściwościami, które można zobaczyć w poniższej tabeli. Należny pamiętać, że typy prymitywne są takie same w każdej implementacji Javy, nieżalenie od sprzętu na którym działa. Małe podsumowanie:

Nazwa Rozmiar
w bitach
Minimalna
wielkość
Maksymalna
wielkość
Klasa wrappera
byte 8 -128 127 Byte
char 16 0 216-1 Character
short 16 -215 215-1 Short
int 32 -231 231-1 Integer
long 64 -263 263-1 Long
Nazwa Rozmiar
w bitach
Minimalna
liczba
Maksymalna
liczba
Klasa wrappera
float 32 1.4e-45 3.4028235e+38 Float
double 64 4.9e-324 1.797e+308 Double
boolean 1 Boolean
void Void

Możemy rozróżnić dwa typy konwersji: rozszerzającą i zawężającą. Konwersja rozszerzająca ma miejsce wtedy, gdy rzutujemy daną wartość na typ o szerszym zakresie danych. Odbywa się ona automatycznie w razie potrzeby. Zgodnie z poniższą konwencją:

Rzutowanie typów prostych

W przypadku typu char następuje rzutowanie do typu int, pomimo tego że typ short ma taką samą wielkość. Jest spowodowane tym, że typ char jako jedyne nie pozwala na zapisanie liczb ujemnych, i tym samym reprezentuje większy zakres liczb.

Podczas konwersji z typu long do typu float może mieć miejsce utrata danych.

Natomiast konwersja zawężająca ma miejsce wtedy, gdy podczas konwersji możemy część danych lub też precyzje obliczeń.

Konwersje zawężające zwykle wymagają odpowiedniego rzutowania. Jeżeli ma miejsce rzutowanie to niezależnie od tego czy tracimy jakieś informacje czy też dane ulegną niespodziewanej zmianie to kompilator nigdy nie wyrzuci żadnego wyjątku w trakcie działania aplikacji. Konwersja zostanie dokonana bez zgłaszania błędów.

Źródła

Tags: , , , , , , , , ,

Modyfikator dostępu protected i default Javie

W Javie możemy za pomocą odpowiednich modyfikatorów dostępu pozwalają decydować, jak dużo metod czy pól klasy udostępnimy innym klasom. Istnieją cztery modyfikatory dostępu:

  • public – pozwala na dostęp do danego elementu ze wszystkich klas
  • protected – pozwala na dostęp do danego elementu tylko dla klas dziedziczących oraz klas z tego samego pakietu
  • default – pozwala na dostęp do danego elementu tylko klasom z danego pakietu (nie istnieje słowo w Javie określające ten rodzaj dostępu, jeżeli chcemy go użyć to po prostu nie podajemy żadnego modyfikatora)
  • private – dostęp do danego elementu ograniczony tylko do klasy w którym jest zdefiniowany

Modyfikator public i private dużego problemu sprawiać raczej nie będzie. Pierwszy umożliwia dostęp do poszczególnej metody bądź pola z każdej klasy, drugi zabrania dostępu każdemu (i przy okazji powoduje, że dany element nie podlega dziedziczeniu). Trochę więcej problemów sprawiają elementy protected i default.

Poniżej znajduje się kod, który demonstruje, kiedy można odwoływać się do zmiennych o modyfikatorach protected i default. Pominąłem modyfikatory private i public, nic nie wnoszą a zaciemniłyby obraz.

KlasaA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//pakietA.KlasaA

package pakietA;

import pakietB.KlasaC;
import pakietB.KlasaD;

public class KlasaA {
    private   int zmiennaPrivate;
              int zmiennaDefault;
    protected int zmiennaProtected;
    public    int zmiennaPublic;
   
    public void zrobCos(KlasaA a, KlasaB b, KlasaC c, KlasaD d) {
        a.zmiennaDefault = 10;
        a.zmiennaProtected = 10;
       
        b.zmiennaDefault = 10;
        b.zmiennaProtected = 10;
       
//      c.zmiennaDefault = 10;
        c.zmiennaProtected = 10;
       
//      d.zmiennaDefault = 10;
        d.zmiennaProtected = 10;
    }
}

KlasaB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//pakietA.KlasaB

package pakietA;

import pakietB.KlasaC;
import pakietB.KlasaD;

public class KlasaB extends KlasaA{
   
    public void zrobCos(KlasaA a, KlasaB b, KlasaC c, KlasaD d) {
        a.zmiennaDefault = 10;
        a.zmiennaProtected = 10;
       
        b.zmiennaDefault = 10;
        b.zmiennaProtected = 10;
       
//      c.zmiennaDefault = 10;
        c.zmiennaProtected = 10;
       
//      d.zmiennaDefault = 10;
        d.zmiennaProtected = 10;
    }
}

KlasaC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//pakietB.KlasaC

package pakietB;

import pakietA.KlasaA;
import pakietA.KlasaB;

public class KlasaC extends KlasaA {
    public void zrobCos(KlasaA a, KlasaB b, KlasaC c, KlasaD d) {
//      a.zmiennaDefault = 10;
//      a.zmiennaProtected = 10;
       
//      b.zmiennaDefault = 10;
//      b.zmiennaProtected = 10;
       
//      c.zmiennaDefault = 10;
        c.zmiennaProtected = 10;
       
//      d.zmiennaDefault = 10;
        d.zmiennaProtected = 10;
    }
}

KatalogD

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//pakietB.KlasaD

package pakietB;

import pakietA.KlasaA;
import pakietA.KlasaB;

public class KlasaD extends KlasaC {
    public void zrobCos(KlasaA a, KlasaB b, KlasaC c, KlasaD d) {
//      a.zmiennaDefault = 10;
//      a.zmiennaProtected = 10;
       
//      b.zmiennaDefault = 10;
//      b.zmiennaProtected = 10;
       
//      c.zmiennaDefault = 10;
//      c.zmiennaProtected = 10;
       
//      d.zmiennaDefault = 10;
        d.zmiennaProtected = 10;
    }
}

Generalnie w odwołaniach można zaobserwować:

  • KlasaB możne odwołać się do wszystkich zmiennych KlasyA (ten sam pakiet, dziedziczenie)
  • KlasaC nie może odwołać się do zmiennych z modyfikatorem default
  • KlasaC może odwołać się do zmiennych oznaczonych jako protected, ale tylko poprzez referencje do KlasyC oraz klas potomnych, nie może się odwołać do tej zmiennej korzystając bezpośrednio z referencji do KlasyA.
  • KlasaA może się odwołać do zmiennych protected we wszystkich klasach potomnych

Źródła

Tags: , , , , ,

Instalacja aplikacji na żądanie w serwerze aplikacji JBoss 6

W wersji 6.0.0M2 serwera aplikacji JBoss pojawiła się nowa funkcja: ładowanie aplikacji serwera na żądanie, czyli dopiero wtedy, gdy przyjdzie zapytanie HTTP o adres, który jest obsługiwany przez daną aplikację.

Powód wprowadzenie tej funkcji jest prozaiczny: ma przyspieszyć czas startu serwera aplikacji. W trakcie tworzenia aplikacji często zachodzi potrzeba restartów serwera aplikacji i wtedy każda dodatkowa sekunda, która poświęca się na czekanie aż wszystkie aplikacje zostaną zainstalowane trwa wieczność :).

Aby włączyć tę funkcję, należy wywołać polecenie run.sh z dodatkowym parametrem:

./run.sh -Djboss.as.deployment.ondemand=true

W środowisku produkcyjnym nie jest zalecane włączanie tej opcji, tam należy preferować uruchamianie wszystkich aplikacji od razu podczas startu serwera aplikacji.

Informacje tu przedstawione dotyczą wersji JBossa 6.0.0M2, więc dalekiej od stabilności. W związku z tym mogą się zmienić.

Źródła

Tags: