Kurs Java Podstawy - rozszerzony

Zakres widoczności zmiennych

Ten kurs zakłada taką sytuację, że nigdy wcześniej nie programowałeś. Warto więc chyba wspomnieć o aspekcie widoczności zmiennych, o tym kiedy ich nazwy mogą się powtarzać, a kiedy się to nie uda. Więcej powiemy o tym, gdy rozpoczniemy omawiać programowanie obiektowe, jednak musimy rozróżniać podstawy,

Zmienne "globalne" w obrębie klasy

Charakteryzują się tym, że są widoczne w obrębie całej klasy, w której je utworzono. W rzeczywistości zmienna taka ma zakres ograniczony do pakietu - może z niej korzystać dowolna klasa w ramach tego samego pakietu.

class JakasKlasa{
 int zmienna_globalna = 5;

 void metoda1(){
    tutaj możesz użyć zmiennej globalnej
 }
}

Przede wszystkim możemy ich używać wewnątrz metod. Zazwyczaj właśnie w tym celu je tak deklarujemy - do komunikacji między metodami w obrębie jednej klasy. Mogłaby to też być stałą do której następują częste odwołania w różnych częściach kodu.

Zmienne "lokalne" w ramach metod

Jak nie trudno się domyślić zakres widoczności, albo może lepiej nazwać to dostępnością, zmiennej  to metoda, lub nawet konkretna pętla.

class JakasKlasa2{
  void metoda(){
      int zmienna_lokalna = 3;
  }

  int zmienna_globalna = zmienna_lokalna; //BŁĄD!
}

Oczywiście powyższy zapis jest błędny nie można się odwołać do zmiennej zadeklarowanej wewnątrz jakiejś metody poza nią samą. Zakres widoczności zmiennych wyznaczają zazwyczaj nawiasy klamrowe.

Dodatkowo zmienne lokalne można deklarować nawet wewnątrz instrukcji sterujących, lub jako licznik w pętli. Zostaną one omówione nieco później, ale spójrzmy jak to działa:

class JakasKlasa3{
  void metoda(){
      if(warunek){
         int a=5;
      }
   //tutaj zmienna "a" jest niewidoczna

  for(int i=0; i<10; i++){  //zmienna obowiązuje tylko w pętli
    System.out.println("Java");
  }
}

Co ciekawe nazwy zmiennych globalnych i lokalnych mogą być identyczne jednak o tym powiemy więcej przy programowaniu obiektowym i pojęciu przesłaniania. Nazwa "globalna" i "lokalna" nie powinna być interpretowana w Javie tak samo jak w innych językach programowania, prawidłowe będzie stwierdzenie "globalna w ramach klasy" w rozumieniu dostępności danej zmiennej w danej klasie (oddzielną kwestią jest dostępność zmiennej między klasami, lub pakietami).

<- Poprzednia LekcjaNastępna Lekcja ->

Komentarze

Robert

Hej. A dlaczego raz piszesz 'metoda' a raz 'metodal' ?
Nie zauważyłem wcześniej żebyś coś o tym wspominał

Slawek

literówki :)
edit: jednak nie literówki - nie ma to znaczenia, jak nazywa się metoda, przykłady chyba kopiowałem z eclipse, gdzie widocznie mi się nazwy duplikowały więc dodałem 1 (jeden).

DJ

Ja zrobiłem tak jak jest w przykładach i przy odpalaniu wyskakuje mi to :
Exception in thread "main" java.lang.NoSuchMethodError: main

Na necie znalazłem to :
public class Lokalne
{
public String my_member_variable = "somedata";

public static void main (String args[])
{
Lokalne yay = new Lokalne();

// Access member variable of demo
System.out.println ("This WON'T generate an error" +
yay.my_member_variable );
}
}

I teraz działa. Dlaczego to co napisałeś mi nie działa?: D

Slawek

W przykładach są klasy, które się kompilują, ale żadna z nich nie zawiera metody main() od której rozpoczyna się działanie programu, więc otrzymujesz wyjątek, że jej nie odnaleziono. Dodam tu w sumie jakiś przykład i zadanie, ale na razie brak czasu na cokolwiek :)

Krzysiek

Dzieki kolo wielki szacun z to co robisz!!!
Chce zostac programista i dlugo szukalem takiego kursu jak ten.Wszedzie bd go polecal.
THX

Jan

Mam taki problem: co zrobić, żeby zmienna z metody była widoczna w całej klasie?:)

Slawek

stwórz sobie zmienną dostępną w całej klasie i przypisz do niej tą wartość?

andrew

Witam.
Jak w poniższym przykładzie użyć zmiennej globalnej "i", aby jej nie deklarować przy każdym użyciu pętli, oraz zamiast zmiennej "z" też użyć zmiennej "i" ?

import java.util.Scanner;

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

System.out.println("Podaj rozmiar calkowity tablicy");
Scanner in=new Scanner(System.in);
int n=in.nextInt();

int[] tab=new int[n];

for (int i=0;i<n;i++)
{
System.out.println("podaj " +(i+1)+" element tablicy");
Scanner in1=new Scanner(System.in);
tab[i]=in1.nextInt();
}


int i=0;
while( i<tab.length){
System.out.println(+(i+1)+" element tablicy to: "+tab[i]);
i++;}


int z=0;
do{
System.out.println(+(z+1)+ "element w tablicy to: "+tab[z]);
z++;
}
while(z<n);

}
}

Witek

Witam
Zaraz pod metodą main( ), możesz zadeklarować zmienne globalne (choć nie koniecznie) np.:

public static void main(String[] args){

int i;
int z;


,które nie są zainicjowane. Następnie w usuwasz z petli for typ danej czyli int, a zostawiasz tylko " i "

for( i = 0; i < n ; i ++) // tu " i " jest inicjowane,

dalej przed pętla While " i " , ma przypisaną nową wartość czyli zero " i = 0; ",
a przed pętlą do { ...... } while, zmiennej „ z „ przypisujesz wartość 0, " z = 0;"

I to wszystko, twój program po wprowadzeniu poprawek takich jak założyłeś u mnie działa, jak będziesz chciał kod to mogę go wkleić.

Witek

Ps.
zmienną " z " możesz zastąpić zmienną " i " , tak jak pokazałem powyżej i też będzie działać.
Pozdrawiam

andrew

Witam.
Proste i logiczne jak budowa cepa. Robiłem tak i już wiem dlaczego nie działało - trzeba pamiętać o wyzerowaniu "i", gdyż po pobraniu elementów tablicy przed pętlami "do" i "while" ma ona wielkość = zmiennej "n". Po zmianie "z" na "i" wszystko huula.
Dzieki Witek za pomoc.

Witek

Nie ma za co.

Janusz

int zmienna_globalna

To niezgodne z konwencją nazewnictwa w Javie, jakby żywce wzięte z jakiegoś kursu C.

Sławek Ludwiczak

zapis dla większej czytelności - konwencje były opisywane wcześniej, w sumie moja wina i nie trzymanie się tego co raz zostało powiedziane. W C niestety nigdy nie programowałem :(

Witek

Witam
Moim zdaniem nazwę zmienna_globalna należy rozumieć, taką zmienną, która widoczna jest w obrębie całej klasy, a np.: zmienna_lokalna widoczna jest tylko w obrębie danego bloku kodu

Sławek Ludwiczak

Januszowi chodzi o coś innego - i w sumie słusznie, że powinno być zmiennaLokalna i zmiennaGlobalna, a nie zmienna_lokalna :)

Me

i niezgodne z konwencją genewską

fokadobra

Literówka: nietrudno zamiast nie trudno

zielonomi

Dlaczego tutaj już nie używa się tego całego public class, później main itd.?

Rafał Mikołajczuk

To już są klasy obiektowe i na ich przypadku najlepiej pokazać zakres zmiennych. Ale fakt, Sławek się troszkę tutaj zagalopował ;). Proponuje Ci przeczytać podstawy o obiektowości, a wszystko zrozumiesz :).

Filu

Tak właściwie do tej lekcji wszystko rozumiałem. Z tej nic, a nic. Nawet w komentarzach nic nie ma co by pomogło, a to dzięki nim doszedłem aż tu. Początkujący.

dawio966

Tutaj zaczynają się schody, trochę mało wytłumaczone co do czego i nie wiem czy mam to skompilować czy nie ;/.

DDO

Może ktoś chce poznać PHP oraz jego mechanizmy obiektowe :-), to są schody.

WBAR

Jest błąd w kodzie:
for(int i=0; i<10; i++) { //zmienna obowiązuje tylko w pętli
System.out.println("Java");
}

(brakuje klamry otwierającej blok kodu)

Sławek Ludwiczak

dzięki, poprawione

Daniel

a mi wyskakuje coś takiego:

JakasKlasa.java:10: error: reached end of file while parsing
}
1 error

Why ? :)

Piotr

Mam dokładnie taki sam problem jak Daniel, wyjaśni ktoś o co z tym chodzi?

Daniel

Akurat jeśli dobrze rozumiem to nie chodzi o 10 linijkę... Ale dalej wyskakuje mi ten błąd :/
@Pite - udało Ci się rozwiązać ten problem?

Marek

Musieliście coś zepsuć w 10 linijce. Co to nie wiem :)

jarek

Może mi ktoś wyjaśnić dlaczego w kodzie są 4 klamry otwierające "{" a tylko 3 zamykające?

Kris

Ktoś mądrzejszy za pewne ode mnie powie mi dlaczego taki oto kodzik nie chce wypisać wyniku??
public class Global{
public static void main(String[] argc)
{
class Global1{
int glob=5;
int wynik;
void dodaj ()
{
wynik=glob+glob;
System.out.print(wynik);
}}}}

lolo

Powód jest bardzo prosty. Nie kazałeś tego zrobić.
W klasie Global masz funkcję main a w niej tworzysz klasę Global1, jednak zapomniałeś stworzyć obiekt klasy Global1 oraz wywołać na nim metodę dodaj().
Dodaj po } zamykającą klasę Globa1 np. taki kod:
Global1 gl = new Global1();
gl.dodaj();
i w konsoli powinien pojawić Ci się wynik.

Sam od niedawna uczę się Javy i mogę się mylić i prosiłbym kogoś bardziej doświadczonego o potwierdzenie bądź zaprzeczenie. Jednak wydaje mi się, że nie powinno się tworzyć klasy w klasie. Dlatego radziłbym dodać definicję klasy dać po za klasę Global.

Kris

Dzięki, teraz działa przyznam się że wcześniej uczyłem się c++ i właśnie wywołania funkcji mi brakowało ale myślałem że to poprostu inny język i nie trzeba... a teraz już wiem :)

Sssmok



jarek:

Może mi ktoś wyjaśnić dlaczego w kodzie są 4 klamry otwierające „{” a tylko 3 zamykające?


Mam ten sam problem. Popuszczeniu skryptu wyskakuje mi w konsoli:
}->
^
1 error
lolo

Drobny błąd który się wkradł. A nikt nie zgłosił go lub Sławek nie zauważył komentarza z informacją błędzie.

Radek

Czy może mi ktoś napisać dlaczego trzeci przykład nie działa?
I dlaczego są 4 klamry otwierające i 3 zamykające?
Czy czegoś przypadkiem nie brakuje?

Adam

Brakuje jeden klamry zamykającej class JakasKlasa3(), a przykład nie działa ponieważ jest tu instrukcja sterująca if() w nawiasie powinniśmy podać "warunek" co przyrównujemy

class JakasKlasa3{
void metoda(){
if(warunek){
int a=5;
}

//TUTAJ ZMIENNA "A" JEST NIEWIDOCZNA

for(int i=0; i<10; i++){ //ZMIENNA OBOWIĄZUJE TYLKO W PĘTLI
System.out.println("Java");
}
}
} // <- brakująca klamra

Tomek

Pisze te programy w Eclipse43 i w JakasKlasa3 wyskakuje mi blad przy lini:
if (warunek){

dlaczego?

Pytanie moze bardzo smieszne ale przy moim poziomie "zaawansowania" to prawdziwy problem

Daniel

Dlatego, że przez „warunek” Kolega miał na myśli np. ( a > 5 )

Pozdrawiam!

Daniel

Przepraszam za małe zamydlenie :-D

Ale źle spojrzałem na kod ;-)
Zatem...:

if( b < 3) {
int a = 5;
}

Czyli jeśli b jest mniejsze od 3 to a przypisana zostanie wartość 5. Jeśli nie to nie ;-)

bartek

Jeszcze takie pytanie bo nie do końca zrozumiałem.
Najpierw piszesz, że zmienna globalna jest dostępna tylko w danej klasie i jej metodach, a poniżej że w pakiecie ?
Przecież pakiet może zawierać wiele klas (plików typu class).
Jak ewentualnie zrobić, żeby zmienna była dostępna we wszystkich klasach danego pakietu ?

Sławek Ludwiczak

Hej. Jeśli klasy są w jednym pakiecie, to zmienna będzie dostępna w drugim pliku, ale w tym drugim pliku musisz utworzyć najpierw utworzyć obiekt pierwszej klasy, a do zmiennych odwoływać się za pomocą operatora kropki.
Nazwa "zmienna globalna" w tej lekcji odnosi się do tego, że masz do niej dostęp z każdego miejsca tej klasy. Masz do niej także dostęp z innych klas, w których utworzysz instancję tej klasy. Jeśli będziesz się chciał odwołać natomiast do pola tej klasy z innego pakietu to będzie to niemożliwe, ponieważ klasy w przykładach mają jedynie zasięg domyślny (nie mają zapisu public class Nazwa {...})
Jeżeli nadal jest problem i potrzebujesz dłuższej odpowiedzi z przykładem, zapraszam do zadania pytania na forum.