Posts Tagged Java

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: , , , , ,

Modyfikatory final i abstract w klasach w Javie

Modyfikator abstract

Modyfikator abstract występujący przy deklaracji klasie oznacza, że mamy do czynienia z definicją, która jest nie kompletna lub też powinna być za taką uważana. Tylko klasa tak oznaczona może zawierać metody, które nie posiadają implementacji. Dana klasa ma metody abstrakcyjne, jeżeli:

  • w klasie jest umieszczona jakakolwiek metoda oznaczona jako abstract
  • jakakolwiek klasa nadrzędna posiada metody abstrakcyjne, które nie zostają implementowane
  • klasa dziedziczy pośrednio lub bezpośrednio interfejs i nie ma implementuje wszystkich jego metod

Klasa abstrakcyjną jest używana w celu uogólnienia zbioru innych klas (zawiera pewne wspólne właściwości tych klas). Może także część tych właściwości definiować, pozwala natomiast zdefiniować interfejs dostępu do innych właściwości, których implementacja musi już nastąpić w którejś klasie potomnej.

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
28
29
30
31
32
33
34
35
36
37
abstract class Figura {

    private int kolor;
   
    public void setKolor(int kolor) {
        this.kolor = kolor;
    }
   
    public abstract void rysuj();
   
}

class Kolo extends Figura {

    private int promien;
   
   
    @Override
    public void rysuj() {
        // implementacja rysowania, przy wykorzystaniu
        // zdefiniowanego wcześniej koloru
    }
}

class Program {
    public static void main(String[] args) {
        Kolo kolo = new Kolo();
       
        Figura kwadrat = new Figura() {
           
            @Override
            public void rysuj() {
                // implementacja rysowania kwadratu
            }
        };
    }
}

Nie można utworzyć obiektu przy wykorzystaniu klasy abstrakcyjnej, jeżeli nie zdefiniuje się wszystkich metod abstrakcyjnych.

Klasa powinna być oznaczona jako abstrakcyjna tylko wtedy, gdy zależy nam na tworzeniu klas potomnych w celu utworzenia pełnej implementacji.

Modyfikator final

Klasa może zostać zdefiniowana jako finalna przy użyciu modyfikatora final. Użycie go przy deklaracji klasy oznacza, że nie można dziedziczyć po danej klasie, jej implementacja jest ostateczna i nie ma możliwości jej modyfikowania.

Przykładami takich klas są np. klasy systemowe: String, Integer czy Long.

1
2
3
4
5
6
7
8
9
10
final class Kwadrat {
   
    int szerokosc;
    int wysokosc;
    int kolor;
   
    public void rysuj() {
       
    }
}

Próba dziedziczenie po podanej klasie spowoduje wygenerowanie komunikatu błędu przez kompilator.

Modyfikatory abstract oraz final wzajemnie się wykluczają (nie można jednocześnie nakazać dziedziczenia oraz zabronić go).

Podsumowanie

Podsumowanie użycia modyfikatorów final i abstract
Modyfikator Użycie w klasie Użycie w interfejsie Użycie w typie enum
abstract Klasa nie finalna może zostać oznaczona jako abstrakcyjna

Klasa która zawiera metody oznaczone jako abstract musi zostać oznaczona także jako abstrakcyjna

Nie można utworzyć obiektu bezpośrednio z klasy abstrakcyjnej (chyba że od razu utworzymy implementację metod abstrakcyjnych)

Dozwolone, ale niepotrzebne,
z założenia interfejs jest abstrakcyjny.
Zabronione.
final Tylko klasa nie abstrakcyjna może zostać oznaczona jako ostateczna.

Klasa zawierająca metody oznaczone jako final nie musi być klasą finalną.

Klasa oznaczona jako final nie może posiadać klas potomnych (nie da się jej rozszerzyć).

Zabronione. Zabronione.

Źródła

Tags: , , , ,

Optymalizacja parametrów JVM dla JBoss AS

W celu przyspieszenia zarówno startu jak i działania serwera aplikacji JBoss można trochę zmodyfikować działanie JVM dodając parametry włączające dodatkowe optymalizacje.

Dwa podstawowe parametry to oczywiście zarządzanie pamięcią:

  • -Xms1024m
    Ustawienie początkowego rozmiaru sterty dla JVM (zalecana ta sama wartość co przy -Xmx).
  • -Xmx1024m
    Ustawienie maksymalnego rozmiaru sterty dla JVM.
  • -XX:MaxPermSize=256
    Ustawienie rozmiaru dla przestrzeni z definicjami klas, istotne w przypadku wystąpienie wyjątku OutOfMemoryError: PermGen space.
  • -XX:+UseLargePages
    Rezerwacja dużych strona pamięci, większych niż standardowe 4kB. Może wpływać negatywnie na wydajność innych aplikacji. Uboczną właściwością użycia dużych stron pamięci w Linuksie jest brak ich możliwości zapisania w pamięci swap (co niekoniecznie musi oznaczać coś złego). Aby używać tego parametru, wcześniej należy skonfigurować odpowiednio system operacyjny, dokumentacja znajduje się pod tym dokumencie: Java Support for Large Memory Pages.
  • -XX:+AggressiveOpts
    Włączenie dodatkowych optymalizacji JVM, które mają zostać włączone dopiero w przyszłych wersji Javy.
  • -XX:+DoEscapeAnalysis
    Po włączeniu tej opcji JVM będzie starał się sprawdzić, czy dany obiekt występuje tylko i wyłączenie w lokalnym zasięgu działania metody. Jeżeli tak, to będzie próbował alokować go bezpośrednio w na stosie bądź też w rejestrach. Dokładny opis można znaleźć w artykułach:

Przykładowa zawartość pliku run.conf:

1
2
3
4
5
6
if [ "x$JAVA_OPTS" = "x" ]; then
 JAVA_OPTS="-Xms128m -Xmx512m -XX:MaxPermSize=256m -Dorg.jboss.resolver.warning=true -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000"
fi

# optymalizacja
JAVA_OPTS="${JAVA_OPTS} -XX:+UseLargePages -XX:+AggressiveOpts -XX:+DoEscapeAnalysis"

Tags: , ,