Kurs Java Podstawy - rozszerzony

Rozwiązanie 2.5

Zadanie polegało tym razem na wykorzystaniu różnych konstruktorów i przetestowania ich działania. Należało utworzyć minimum 3 konstruktory z różnymi parametrami, w przykładowym rozwiązaniu stworzyłem:

  • Konstruktor domyślny inicjujący pola klasy nieprawdziwymi danymi - dzięki temu, gdyby ktoś przypadkiem próbował się odwołać do naszego obiektu nie otrzyma komunikatu wyjątku NullPointerException.
  • Konstruktor inicjujący pola klasy odpowiednimi danymi podanymi jako argumenty.
  • Konstruktor przyjmujący inny obiekt klasy Pracownik - przydatne, gdy chcemy coś na przykład powielić.

Odpuściłem sobie konstruktory przyjmujące przykładowo tylko imię i wiek, ponieważ nie widzę jego zastosowania a jakiejś rzeczywistej aplikacji.

public class Pracownik{
	String imie;
	String nazwisko;
	int wiek;

	public Pracownik(){
		imie = "nie_podano";
		nazwisko = "nie_podano";
		wiek = -1;
	}

	public Pracownik(String i, String n, int w){
		imie = i;
		nazwisko = n;
		wiek = w;
	}

	public Pracownik(Pracownik prac){
		imie = prac.imie;
		nazwisko = prac.nazwisko;
		wiek = prac.wiek;
	}
}

W klasie Firma należy jedynie przetestować to co tutaj stworzyliśmy. Utwórzmy więc 3 obiekty i wyświetlmy na ekranie ich pola imie, nazwisko i wiek.

public class Firma{

	public static void main(String args[]){
		Pracownik[] pracownicy = new Pracownik[3];
		pracownicy[0] = new Pracownik();
		pracownicy[1] = new Pracownik("Staszek", "Kowalski", 34);
		pracownicy[2] = new Pracownik(pracownicy[1]);

		for(Pracownik p: pracownicy)
			System.out.println("prac3: "+p.imie+" "+p.nazwisko+" "+p.wiek);
	}
}

Komentarze

Tomasz

Witam, rozwiązałem to zadanie troche inaczej niz jest to w tutaj pokazane [troche sie wspomagałem tym], wszystko mi dobrze działa, ale chciałbym upewnić się czy nie robię czegoś głupiego w kodzie, bezużytecznego, itp.. Dla przypomnienia starałem się używać wszystkiego po trochu, dlatego tak duzo wyszło...

klasa Pracownik identycznie wygląda jak tutaj, natomiast Firma:

public class Firma{
public static void main(String args[]){
Pracownicy[] pracownik = new Pracownicy[5];

String[] Imiona = new String[5];
String[] Nazwiska = {"Przykladowy", "Kowalski", "Nowak", "Zly", "Dobry"};
int[] Wiek = {20, 25, 30, 34, 55};

Imiona[0]="Tomasz";
Imiona[1]="Jan";
Imiona[2]="Kaziemierz";
Imiona[3]="Bonifacy";
Imiona[4]="Lucjan";

for(int i=0; i<pracownik.length; i++){
pracownik[i] = new Pracownicy(Imiona[i], Nazwiska[i], Wiek[i]);
System.out.println("\nImie: "+pracownik[i].Imie+"\nNazwisko: "+pracownik[i].Nazwisko+"\nWiek: "+pracownik[i].Wiek);
}
}
}

Arkadiusz


public Pracownik(Pracownik prac){
imie = prac.imie;
nazwisko = prac.nazwisko;
wiek = prac.wiek;
}

Czy mogę prosić o wyjaśnienie tego, dlaczego tak?

Slawek

Po prostu tworzymy jakiegoś pracownika na podstawie innego. Przypisujemy odpowiednie wartości z istniejącego już pracownika. Należy jednak uważać, ponieważ przy typach referencyjnych mogą być problemy - edytując wartości z jednego obiektu będą modyfikowane także te z obiektu oryginalnego - należy w takich sytuacjach używać tzw. głębokiego klonowania (deep clone).

Arkadiusz

Oraz jeszcze jedno, napisałem teki kod:

public class Firma {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub

Pracownik pracownik = new Pracownik(" ","Kowalski",25);
pracownik.wyswietl();


}

}

oraz drugi pliczek


public class Pracownik {

String imie="Nie_Podano";
String nazwisko;
int wiek;

//Tworzymy konstruktr

public Pracownik(String pimie, String pnazwisko, int pwiek){

imie=pimie;
nazwisko=pnazwisko;
wiek=pwiek;

}

public Pracownik(Pracownik prac){

imie = prac.imie;
nazwisko = prac.nazwisko;
wiek= prac.wiek;


}


void wyswietl(){
System.out.println(" "+imie+" "+nazwisko+" "+wiek);

}



}


wynik wywołania

Kowalski 25

Co powinienem zmienić(doczytać) w sytuacji kiedy nie podamy jednego z parametrów zostanie wywołany domyślna wartość z konstruktora?

Slawek

Jeżeli mamy ten przykładowy konstruktor Pracownik(String imie, String nazwisko, int wiek), to pominięcie parametru nie wchodzi w rachubę - otrzymamy błąd kompilacji. W gestii twórcy klasy jest to, żeby dostarczyć wszystkie sensowne konstruktory, które mogą być później przydatne.
W niektórych sytuacjach można wykorzystać sztuczkę z tzw Varargs.
Przykładowo tworzymy sobie klasę Drużyna, która przechowuje jakieś tam oznaczenia zawodników i ma taki konstruktor:
Druzyna(int... numery) {
//numery to tak naprawdę tablica wartości, odwołujemy się do niej jak przy tablicach numery[0] itd. Możemy tutaj przekazać zarówno 1, jak i 10 argumentów. Jest tylko haczyk, parametr typu varargs może być jedynie ostatnim parametrem w konstruktorze / metodzie.
}
poprawne będą wywołania:
new Druzyna();
new Druzyna(1);
new Druzyna(1, 2, 3, 4); //ilość argumentów w zasadzie nieograniczona

Hubert

Witam,

Czy mógłby ktoś dokładniej omówić działanie pętli for_each wykorzystanej w tym przykładzie? Jak dobrze myślę to "p" pełni tu rolę aliasu? Ale ogólnie troche nie rozumiem tego zapisu

Shutah

Działa to bardzo prosto.

Pracownik p: pracownicy
----------------------------
- [Pracownik] to jakby typ, na którym operujemy, tak samo jak int, double czy String.
- [p] to poszczególne elementy tablicy (obiekty), do których wartości odnosimy się wyświetlając dane np. p.wiek.
- [pracownicy] to po prostu tablica na której wykonujemy operacje.

Sowa

ja też bym prosił o wyjaśnienie :)

bartek

No to ja napisałem swoje...

public class Pracownik{

String imie;
String nazwisko;
int wiek;

// konstruktory
public Pracownik = new Pracownik(){
imie = "brak";
nazwisko = "brak";
wiek = -1;
}
public Pracownik = new Pracownik(String i, String n, int w){
imie = i;
nazwisko = n;
wiek = w;
}
public Pracownik = new Pracownik(String i, String n){
imie = i;
nazwisko = n;
wiek = -1;
}
public Pracownik = new Pracownik(String n){
nazwisko = n;
imie = "brak";
wiek = -1;
}
public Pracownik = new Pracownik(Pracownik prac){
nazwisko = prac.nazwisko;
imie = prac.imie;
wiek = prac.wiek;
}

// metody
void show(){
System.out.println(imie+" "+nazwisko+" "+wiek);
}
}



public class Firma{

public static void main(String[] args){

String[] imiona = {"a","b","c"};
String[] nazwiska = {"X","Y","Z"};
int[] lata = {21,20,19};

Pracownik p = new Pracownik[3];
for(int i=0; i<imiona.length; i++){
p[i] = new Pracownik(imiona[i],nazwiska[i],lata[i]);
p[i].show();
}
}
}


I niestety wyrzuca mi 49 błędów, a pierwszym z nich jest:


.\Pracownik.java:8: error: expected
public Pracownik = new Pracownik(){
^


Coś wiadomo co i dlaczego tak się mogło stać?

Witek

Witam
W klasie Pracownik masz źle zrobione konstruktory, powinny wyglądać tak:
public Pracownik(); .
Natomiast w klasie Firma błąd polega na tym , że nie dodałeś [] tablicy.
Powinno być tak:
Pracownik p[] = new Pracownik[3];
Po wprowadzeniu poprawek twój program u mnie się kompiluje i uruchamia.

kamil2321

A mi jakoś nie ;)
Błędów sporo ;c

Tomek

Cześć.
Rozwiazalem to zadanie przy pomocy strumieni wej/wyj. mianowicie uzytkownik wprowadza dane - w zaleznosci od tego ile ich poda wywolywany jest odpowiedni konstruktor.
i tutaj mam pewną zagłostkę MIANOWICIE:
komplet danych to: string, string, int. Mozemy zalozyc, iż uzytkownik poda jedynie imie i wiek. Jak rozroznic sytuacje (w konstruktorze?) jesli podajemy:
1. imie, wiek
2. nazwisko, wiek
nie mozemy stworzyc dwoch konstruktorów pobierajace te same parametry (string, int).
Prosze o pomoc :)

Sławek Ludwiczak

Nie mam pojęcia jak pobierasz dane od użytkownika, ale chyba zawsze musisz pobrać imię, nazwisko i wiek - bo nie wiem jakbyś chciał rozróżniać, czy coś jest imieniem, czy nazwiskiem. Stwórz po prostu konstruktor z 3 argumentami i jeśli nie ma imienia, lub nazwiska to podaj jako argument null, przy warunku, że przynajmniej jedna ze zmiennych imie, lub nazwisko nullem być nie może.

Tomek

Hmm... dzieki. Zaraz postaram sie to poprawic.
Poprostu zalozylem sobie, ze uzytkownik nie jest doskonały i nie podaje 3 argumentów. Ot taki testerski nawyk ;)

Sławek Ludwiczak

Użytkownik nie musi być doskonały i może podać 2 argumenty, ale w tym przypadku nie widzę innego wyjścia jak stworzenie idiotoodpornego systemu. Aplikacja nie rozpozna, czy ktoś podał imię, czy nazwisko (tym bardziej, że istnieją nazwiska identyczne jak imiona).
Jeśli już to musiałbyś to po prostu rozpoznawać jakimś if'em, lub switch'em w samym konstruktorze.

Pav

Hmmm, myślałem 2 godziny jak tu wstawić tabelę z pętlą ale nie spodziewałem się że będzie ona zawierać:
prac3: nie_podano nie_podano -1
prac3: Staszek Kowalski 34
prac3: Staszek Kowalski 34
Myślałem,że chodzi o coś na wzór Rozwiązania 2.2

Jak zwykle nie mogę zrozumieć polecenia.

Pav

Po przeczytaniu rozwiązania rozumiem o co chodzi ( mam już trochę doświadczenia z językami, np. skryptowymi, wiem że trzeba zabezpieczyć się przed błędami ) tylko jakoś nie zawsze mogę nadążyć za autorem, zresztą podobnie było właśnie z rozwiązaniem 2.2, albo robimy test z przydatności małego kawałka kodu albo trzeba wejść na wyżyny i wymyślić coś o czym jeszcze nie było mowy. A poza tym szacunek za wiedzę i chęci dzielenia się nią.

Ignacy

Albo od paru lekcji Twoje zadania wyprzedzają to co było na danej lekcji, albo jestem mało inteligentny. Raczej bardziej prawdopodobne jest to drugie :)
Gratuluje kursu, naprawdę świetny: zarówno dla tych, co spotkali się wcześniej z programowaniem, jak i dla tych, co nigdy wcześniej tego nie robili (jak ja). Tak trzymaj!

Przemek

a ja zrobilem nieco inaczej:


class Pracownik {

private String imie;
private String nazwisko;
private String miasto;
private int wiek;
private int pensja;


public Pracownik (String i,String n,String m, int w,int p){
imie = i;
nazwisko = n;
miasto = m;
wiek = w;
pensja = p;
}

public String opis(){
return ("Pracownik: " + imie + " " +nazwisko+ ", Zamieszkały w: " +miasto+ ", Lat: " +wiek+ ", Pensja: " +pensja);

}
}



public class Firma {
public static void main(String[] args){

Pracownik prac1 = new Pracownik("Przemyslaw", "Zadomski", "Gdańsk", 22, 3500);
Pracownik prac2 = new Pracownik("Anna", "Grygorowicz", "Gdańsk", 18, 3000);
Pracownik prac3 = new Pracownik("Tomasz", "Gałaj", "Łódź", 22, 3500);
Pracownik prac4 = new Pracownik("Jakub", "Michalewki", "Ely/Anglia", 31, 4500);

System.out.println(prac1.opis());
System.out.println(prac2.opis());
System.out.println(prac3.opis());
System.out.println(prac4.opis());



}
}

Krystian

Na podstawie pierwszego przykładu o pracowniku i firmie:

public class Pracownik1 {
String imie;
String nazwisko;
int wiek;

public Pracownik1(){ }

public Pracownik1(String a, String b, int c){
imie = a;
nazwisko = b;
wiek = c;
}

public Pracownik1(Pracownik1 prac){
imie = prac.imie;
nazwisko = prac.nazwisko;
wiek = prac.wiek;
}
}

public class Firma1 {
public static void main(String[] args){
Pracownik1[] pracownik = new Pracownik1[3];
String[]imiona = {"robert","rafał","zbyszek"};
String[]nazwiska = {"mały","pyzł","chum"};
int[]lata = {21,22,23};

for(int i=0;i<pracownik.length;i++){
pracownik[i] = new Pracownik1();
pracownik[i].imie =imiona[i];
pracownik[i].nazwisko = nazwiska[i];
pracownik[i].wiek = lata[i];
}
for(int i=0;i<pracownik.length;i++)
System.out.println(""+pracownik[i].imie+" "+pracownik[i].nazwisko+" "+pracownik[i].wiek+" ");
}
}

Chyba dobrze :D

k2marko

Też zrobiłem to w podobny sposób. Obawiam się jednak, że to nie tak miało wyglądać. Zwróć uwagę, że w klasie Firma praktycznie nie korzystasz z utworzonych wcześniej konstruktorów w klasie Pracownik. Równie dobrze mógłbyś usunąć te konstruktory i wszystko nadal działałoby tak samo.

Mario

A można to rozwiązać bez tablic np w taki sposób? :

class Pracownik{
String imie;
String nazwisko;
int wiek;

public Pracownik(String imie){
System.out.println("Imie to: "+imie);
}

public Pracownik(String nazwisko, int wiek){
System.out.println("Nazwisko to: "+nazwisko+" "+ wiek);
}

public Pracownik(int wyplata, String zl){
System.out.println("Wyplata: "+ wyplata+""+zl);
}
}

public class Firma{
public static void main(String[] args){
Pracownik pracownik = new Pracownik("Waldek");
Pracownik pracownik1 = new Pracownik("Rola", 33);
Pracownik pracownik2 = new Pracownik(1500,"zl");
}
}

Wynik działania programu:
Imie to: Wladek
Nazwisko i wiek to: Rola, 33
Wyplata to: 1500zl

aleksanderwiel

Chyba autor tego zadania popełnił błąd, bo w klasie "Fima" mam błąd z tymi konstruktorami. Po prostu wywala mi przy nich błędy, czyli przy tych tablicach, a w nich konkretnie ten fragment, czyli to w nawiasach, np. "p." i "pracownicy[1]".

pracownicy[1] = new Pracownik("Staszek", "Kowalski", 34);
pracownicy[2] = new Pracownik(pracownicy[1]);
for(Pracownik p: pracownicy)
System.out.println("prac3: "+p.imie+" "+p.nazwisko+" "+p.wiek);

Czy może mi ktoś wyjaśnić, skąd te błędy?

lolo

A te błędy mają jakąś treść może?