Java

Java jest językiem programowania zorientowanym na programowanie w paradygmacie obiektowym. Poniżej opisane są podsawowe założenia twórców tego języka.

Obiektowość i dziedziczenie

Obiektowość

Programowanie obiektowe polega na definiowaniu programów za pomocą obiektów, a program komputerowy napisany obiektowo wyrażony jest jako zbiór obiektów komunikujących się ze sobą w celu wykonania określonych zadań. Obiektowość w Javie opiera się na pojęciu klasy - modułu posiadającego nazwę oraz atrybuty w postaci metod i pól klasy. Klasy służą do zdefiniowania typu danych, którego elementy nazywane są obiektami, a referencje do tych obiektów są wartością zmiennych obiektowych. Innymi słowy obiekty są egzemplarzami klasy. Poza typami prostymi (np. int, float) w Javie wszystko jest obiektem.

Dziedziczenie

Dziedziczenie jest mechanizmem charakterystycznym dla programowania obiektowego i umożliwiającym definiowanie nowych klas na bazie innych, już istniejących. Działanie tego mechanizmu polega na przejmowaniu przez jedną klasę (dziedziczącą) metod i zmiennych innej klasy. Wszystkie obiekty dziedziczą po klasie Object.

Wielodziedziczenie

Język Java nie posiada mechanizmu wielodziedziczenia. Oznacza to, że dana klasa może rozszerzać tylko jedną klasę bazową. Twórcy języka zdecydowali się na takie rozwiązanie aby ułatwić pracę programiście. Problem wielodziedziczenia dotyczy jedynie implementacji, zatem nie dotyczy on interfejsów. Tak więc zamiennikiem wielodziedziczenia w Javie jest umożliwienie jednej klasie implementowania wielu interfejsów. Co więcej w Javie 8 pojawiła się nowa możliwość - dodanie domyślnej implementacji metod interfejsów. Zmiana ta stanowi krok w kierunku upodobnienia mechanizmu wielodziedziczenia interfejsów do mechanizmu wielodziedziczenia klas znanego np. z C++.

Brak wpływu architektury na działanie programów

Kolejnym celem twórców Javy jest przenośność, co oznacza, że program napisany na platformę Java musi działać podobnie na dowolnej kombinacji sprzętu i systemu operacyjnego, które zapewnią odpowiednie wsparcie wykonania. Cel ten osiągnięto przez podjęcie decyzji o kompilowaniu kodu źródłowego do kodu pośredniego nazywanego kodem bajtowym Javy. Instrukcje kodu bajtowego są analogiczne do kodu maszynowego, ale ich przeznaczeniem jest wykonanie przez wirtualną maszynę Javy (JVM) napisaną i przystosowaną do konkretnego systemu operacyjnego i sprzętu komputerowego. Użycie kodu bajtowego zapewnia przenośność, jednak odbywa się to kosztem czasu wykonania programów.

Niezawodność i bezpieczeństwo

Java posiada mechanizmy pozwalające uniknąć często powtarzających się błędów:

Automatyczne zarządzanie pamięcią

W celu zarządzania pamięcią Java wykorzystuje automatyczny odśmiecacz. Programista określa kiedy obiekty są tworzone, a za odzyskanie pamięci zajmowanej przez nieużywane obiekty odpowiada środowisko uruchomieniowe Javy. Głównym celem automatycznego zarządzania pamięcią jest odciążenie programisty, aby nie musiał pamiętać o zwalnianiu miejsca po nieużywanych obiektach. Nie jest jednoznacznie określone kiedy uruchamiane jest odśmiecanie, jednak wiadomo, że będzie uruchomione zawsze gdy zabraknie pamięci do zaalokowania dla nowego obiektu.

Silne statyczne typowanie

Każde wyrażenie ma ustalony typ, a użycie tego wyrażenia w kontekście przeznaczonym dla innych typów spowoduje błąd kompilacji. Każda zmienna musi mieć podany typ podczas jej deklaracji.

Obsługa wyjątków

Wyjątek jest zdarzeniem, które występuję zazwyczaj na skutek błędu i powoduje przerwanie normalnego wykonania programu. Przyczyną powstania sytuacji wyjątkowej może być na przykład próba otworzenia nieistniejącego pliku, odwołanie się do elementu tablicy spoza zakresu czy operacje na elemencie pustym. Obsługa wyjątków polega na dodaniu do programu kodu, który wykona się w momencie wystąpienia sytuacji wyjątkowej.

Asercje

Przy wywołaniu programu z odpowiednią opcją asercje umożliwiają sprawdzenie czy założenia programisty dotyczące działania wybranych fragmentów kodu są prawdziwe.

Przykładowy kod


class Bicycle {
    private int gear;
    private int speed;
        
    public Bicycle(int startSpeed, int startGear) {
        this.gear = startGear;
        this.speed = startSpeed;
    }
        
    public void setGear(int newValue) {
        this.gear = newValue;
    }
        
    public void applyBrake(int decrement) {
        this.speed -= decrement;
    }
        
    public void speedUp(int increment) {
        this.speed += increment;
    }
    
    @Override
    public String toString(){
    	return "Bicycle: gear - " + this.gear + ", speed - " + this.speed;
    }       
}
      


class MountainBike extends Bicycle {
        
    private int seatHeight;

    public MountainBike(int startHeight, int startSpeed, int startGear) {
        super(startSpeed, startGear);
        this.seatHeight = startHeight;
    }   
        
    public void setHeight(int newValue) {
        this.seatHeight = newValue;
    }
    
    @Override
    public String toString(){
    	return super.toString() + ", seat height - " + this.seatHeight;
    }

}
	  

public static void main (String[] args) throws java.lang.Exception{
	Bicycle b= new Bicycle(20,30);
	Bicycle mb = new MountainBike(55, 25, 15);
	System.out.print(b);
	System.out.print(mb);
}