Laboratorium 1

Wstęp. Różnice pomiędzy C++ a Javą.

 

A. Wstęp.

Pamiętacie najprostszy kod wypisujący napis na ekran w C++? Tak wygląda to w Javie: 

Hello World: C++ Hello World:  Java
#include <iostream>
 
using namespace std;
 
int main(int argc, char** argv)
{
    cout<<"Hello World!";
    return 0;
}
 
class Hello
{
    public static void main(String[ ] args)
    {
        System.out.println("Hello World!");
    }
}

 

Podstawowe pętle i instrukcje warunkowe są identyczne w obu językach:

Kod działający zarówno w C++ jak i w Javie
int foo=1, bar=3;
if (foo == 1) {
  foo=2;
}
else {
  foo=3;
}
for (int ii = 0; ii < bar; ii++){
  bar += 5 % 2;
}

 

Kompilacja: C++ Kompilacja: Java
g++ [lista plików do skompilowania]
javac [lista plików do skompilowania]
Wynik kompilacji: C++ Wynik kompilacji: Java
program: a.out
plik .class: Hello.class

 

W Javie po poprawnej kompilacji tworzone są pliki .class, które mogą być uruchomione w dowolnym systemie operacyjnym posiadającym Wirtualną Maszynę Javy (JAVA VM).

Uwaga: Nazwy plików z kodem źródłowym Javy NIE SĄ dowolne:

  1. muszą mieć rozszerzenie .java.
  2. w przypadku deklarowania klasy publicznej, nazwa pliku musi być identyczna z nazwą klasy (wielkość liter ma znaczenie)

Przykładowo, klasa:

public class Example {...} musi być zadeklarowana w pliku Example.java i w wyniku kompilacji utworzy  Example.class

 

Uruchomienie: C++ Uruchomienie: Java
./a.out
java [nazwa pliku class]

 

Uruchomienie z argumentami: C++ Uruchomienie z argumentami: Java
./a.out arg1 arg2
java [nazwa pliku class] arg1 arg2

 

Tablice

A oto przykład deklaracji tablic w Javie (w porównaniu z C++).

   
Tablice: C++ Tablice:  Java
double myList1[10];

double* myList2; //deklaracja
myList = new double[10]; //utworzenie tablicy

double* myList = new double[10]; //dwa w jednym

double total = 0;
for (int i = 0; i < 10; i++) {
  total += myList[i];
}

delete [] myList;
delete [] myList2;
double[] myList1 = new double[10];

double[] myList2; //deklaracja
myList = new double[10]; //utworzenie tablicy

double[] myList = new double[10]; //dwa w jednym

double total = 0;
for (int i = 0; i < myList.length; i++) {
  total += myList[i];
}
			           
 
 

Co należy zauważyć:

  • W Javie nie występują "tablice statyczne". Tablice zawsze deklarujemy przez new.
  • Nie ma delete! W Javie Garbage Collector czyści pamięć za nas.
  • Pole length tablicy przechowuje jej długość.
  • Odczyt oraz zapis do poszczególnych komórek tablicy jest taki sam w obu językach.

 

B. Eclipse

Na zajęciach nie będziemy jednak pisać w notatniku, tylko korzystać ze środowiska Eclipse. Eclipse to bardzo popularne zintegrowane środowisko programistyczne (ang. IDE), czyli zespół aplikacji służących do tworzenia, modyfikowania, testowania i konserwacji oprogramowania. Pozwala na instalację dużej ilości różnych wtyczek, dopasowanych do potrzeb programisty. Więcej informacji: tutaj.

Podstawowe informacje które mogą się przydać dzisiaj na zajęciach:

1. Po uruchomieniu zostaniesz zapytany o workspace - katalog, w którym będą zapisywane nowe projekty

2. Tworzenie nowego projektu w Eclipse

Wystarczy wybrać z menu: (File/New/Project... -> Java Project -> wybrać nazwę projektu -> Finish)

3. Dodanie do projektu nowej klasy

 File/New/Class -> wybrać nazwę klasy -> Finish)

4. Dodanie do projektu nowej klasy zawierającej metodę main

 File/New/Class -> wybrać nazwę klasy i zaznaczyć pole dodające metodę main -> Finish)

5. Uruchamianie programu z argumentem w środowisku Eclipse: Run -> Run Configurations -> wybrać zakładkę arguments -> wpisać argumenty programu
 
Paczki java (package i import)

W dużych środowiskach problemem może być zderzenie nazw pomiędzy różnymi klasami należącymi do dwóch projektów które trzeba połączyć. 

Wyobraźmy sobie taki scenariusz:  sprzedawca mebli posiadający napisany w Javie system sprzedażowo-magazynowy chce rozwinąć się w kierunku sprzedaży detalicznej i postanowił stworzyć sklep internetowy i w tym celu zakupił gotowy CMS napisany w Javie oparty o Javę EE. Niestety, jego istniejący system sprzedażowy zawiera klasę o nazwie Table.java która reprezentuje różne stoły jakie opisywana firma sprzedaje. CMS również operuje klasą Table.java, która reprezentuje tabelkę HTML. Bez operowania przestrzeniami nazw (w javie określa się je paczkami) nie da się tych dwóch projektów połączyć, bo kompilator nie wiedziałby do której z klas odnosi się np. wywołanie: 

Table table = new Table();

Jak umieścić klasę w paczce?
Jeśli chcemy umieścić naszą klasę w paczce o nazwie 
foo.bar musimy dodać dyrektywę  package foo.bar; jako pierwszą linię w treści klasy.

Wszystkie klasy należące do tej paczki znajdują się w katalogu foo/bar

  • Jeśli mówimy o kodzie źródłowym, to znajdują się one w tym katalogu wewnątrz katalogu ze źródłami projektu.
  • Jeśli mówimy o skompilowanym kodzie, to znajdują się one w katalogu foo/bar katalogu głównego w pliku .jar lub katalogu dodanego do classpath

Import klas z paczki

By odnieść się do klasy Baz z paczki foo.bar możemy podać jej pełną (kwalifikowaną) nazwę:

 

foo.bar.Baz baz = new foo.bar.Baz();

Operowanie pełnymi nazwami jest niewygodne, ale czasem jest konieczne.

Przykładowo, gdy operujemy kilkoma klasami o tej samej nazwie (w przykładzie klasy Baz z paczek foo i bar).

 

 

foo.Baz baz = new foo.Baz();

bar.Baz baz = new bar.Baz();

 

By skrócić ilość pisania, możemy użyć dyrektywy  import, która pozwala ominąć nazwę paczki. Proszę pamiętać że dyrektywa import znaczy tak naprawdę: "Drogi kompilatorze, wiedz, że od tej pory, gdy napiszę nazwę klasy Baz, chodzi mi o klasę Baz z paczki foo.bar:

 

import foo.bar.Baz;

 

Związek między klasami w paczce

Klasy w jednej paczce widzą się nawzajem, tj. nie potrzeba ich importować.

Dodatkowo klasy z jednej paczki mają ułatwiony dostęp do swoich atrybutów. Wyobraźmy sobie taką klasę:

package foo.bar;

class Foo{
  private int priv;
  int pack;
  protected int prot;
  public int pub;
  private void doNothingPrivate(){};
  void doNothingPack(){};
  protected void doNothingProt(){};
  public void doNothing(){};
}


Klasy z paczki foo.barnie mają dostępu tylko do atrybutu priv i metody doNothingPrivate.

 

Zadanie A - Hello i pętla. (1 pkt)

Utworzyć nowy projekt, a następnie utworzyć w nim plik tekstowy (File → New → File) o nazwie Hello.java.  Następnie należy napisać w jego wnętrzu program wypisujący na ekranie słowa "Witaj!" a pod spodem liczby od 1 do [pierwszego_argumentu_programu]. Klasa powinna znajdować się w paczce pojava.lab1.zadA. Następnie należy skompilować go i uruchomić. 

Wskazówki:

  1. Najpierw napisz program, który wyświetla liczby od 1 do X, gdzie X = 20.

          2. Zmień X na w ten sposób, by X było argumentem przekazywanym z zewnątrz do metody main(String[] args).

  • Należy zauważyć, że argumenty przekazywane są do funkcji main w postaci tablicy obiektów klasy String. Czyli argumenty wywołania programu można znaleźć pisząc args[1], args[2], itp... 

  • Zamiana String na int: 

    String myString = "1234";
    int myInt = Integer.parseInt(myString);
  • Program powinien wyświetlać informację o błędzie jeśli użytkownik nie poda argumentu. Najłatwiej sprawdzić, czy długość tablicy args jest równa 0.

 

Zadanie B - Tablica String. (1.5 pkt)

Używając środowiska Eclipse napisz program, który utworzy tablicę na 4 ciągi znaków (String), wypełni ją słowami (cztery pierwsze parametry wywołania programu) po czym wypisze na ekranie. Klasa powinna znajdować się w paczce pojava.lab1.zadB.

 

C. Klasy i Dziedziczenie

Każdy pisany w Javie kod znajduje się w obrębie jakiejś klasy. Żeby stworzyć obiekt klasy i wywołać jego metody należy użyć operatora new:

KlasaPrzykladowa kp = new KlasaPrzykladowa();

Pamiętaj: obiekty w Javie zawsze tworzone są przy pomocy operatora new po którym następuje konstruktor (czyli nazwa klasy wraz z ewentualnymi argumentami).

 

Dziedziczenie jest znanym państwu z C++sa mechanizmem współdzielenia funkcjonalności pomiędzy klasami:  

Dziedziczenie: C++ Dziedziczenie:  Java
class Bazowa
{
  public:
  Bazowa();
};

class Pochodna : public Bazowa
{
};
class Bazowa
{
  public Bazowa();
};

class Pochodna extends Bazowa
{
};

 

Co należy zauważyć:

  • Słowo kluczowe extends mówi o dziedziczeniu z klasy nadrzędnej
  • Nie ma już dwukropków po modyfikatorach dostępu (public / private itp.), każda funkcja składowa klasy i konstruktor posiada własny modyfikator dostępu.
  • Domyślnym modyfikatorem nie jest już "private" jak w C++, lecz "package protected", czyli dana funkcja / klasa / pole jest dostępne z każdego miejsca danej paczki.

 

Zadanie C - Dziedziczenie (2.5 pkt)

Proszę stworzyć klasę Auto, która zawiera:

  • pole: float[] przebieg; - to tablica przechowująca informację o ilości przejechanych kilometrów w kolejnych miesiącach, jej rozmiar to 12; Tablica jest inicjalizowana losowymi wartościami w konstruktorze.
  • metodę: float srPrzebieg(); - oblicza średni przebieg dla samochodu.
  • nie posiada metody main

Proszę stworzyć klasę Taxi, która dziedziczy po klasie Auto i zawiera:

  • pole: float[] zarobki; - to tablica przechowująca informację o zarobkach taksówkarza kolejnych miesiącach, jej rozmiar to 12; Tablica jest inicjalizowana losowymi wartościami w konstruktorze.
  • metodę: float srZarobki(); - oblicza średnie zarobki dla taksówki. 
  • posiada metodę main w której proszę stworzyć obiekt klasy Taxi i wyświetlić na ekranie średni przebieg i średnie zarobki.

 

Wskazówka:

  • każdą klasę należy zadeklarować w oddzielnym pliku (o nazwie danej klasy)
  • konstruktory w Javie deklaruje się tak samo jak w C++,
  • dziedziczenie również deklaruje się tak samo jak w C++, należy jedynie pamiętać o słowie extends zamiast dwukropka
  • funkcję losującą liczby zmiennoprzecinkowe z danego zakresu (przy wypełnianiu tablic przebieg, zarobki) należy samodzielnie znaleźć w internecie

Poniżej kod dla dwóch przykładowych klas: bazowej i pochodnej.

 

Klasa bazowa
package pl.wyklad1.klasapokazowa;
public class KlasaPrzykladowa {

// deklaracje konstruktorow
KlasaPrzykladowa() {
  x = 0;
  tekst = "domyslny";
  //to jest konstruktor domyslny
}

// deklaracje metod
void setX(int aX) {
  x = aX;
}

int getX() {
  return x;
}

void wypisz() {
  System.out.println(x + " " + tekst);
}

// deklaracje pol
int x;
String tekst;

Klasa pochodna
public class KlasaPochodna extends KlasaPrzykladowa {

KlasaPochodna(){
  x = 1;
  tekst = "domyslny pochodnej";
  //konstruktor domyslny
} 

public void wypisz(){
  System.out.println(x + " " + y + " " + tekst);
} 
int y = 10;
}
Funkcja główna main
public static void main(String[] args) {
  KlasaPochodna kp = new KlasaPochodna();
  kp.wypisz();
}