We weten allemaal dat landen grenzen hebben en hun eigen wetten. De wetten van het land werken binnen de grenzen. Ook in het land zijn er bijvoorbeeld organisaties, zoals scholen of musea, die hun eigen lokale regels hebben. Ze zijn niet in tegenspraak met de wetten van het land, maar werken alleen binnen het kader van de gespecificeerde organisatie. Hetzelfde geldt voor programmeren. Dus in de programmering, en met name in de Java-taal, is er een term "scope". Het verwijst naar delen van het programma waar bepaalde gegevens, zoals variabelen of methoden, werken. In dit artikel gaan we uitzoeken wat de scopes zijn voor variabelen in Java en hoe ze te definiëren.

Java-scope in het algemeen

Waarom is het nodig om scopes van variabelen en methoden te scheiden? Feit is dat programma's soms erg groot zijn en dat het moeilijk kan zijn om een ​​of andere variabele te volgen. Daarnaast is bij grote projecten een duidelijke naamgeving van variabelen wenselijk zodat duidelijk is waarvoor ze dienen. Met Scope kunt u specifiek verschillende variabelen met dezelfde naam in verschillende delen van het programma hebben. Dergelijke code is gemakkelijker te onderhouden en te lezen. Java-scope definieert waar een bepaalde variabele of methode toegankelijk is in een programma. Kort:
  • Een variabele die in een methode is gedeclareerd, is zichtbaar vanaf het begin van de declaratie tot het einde van de methode (methodebereik).
  • Een variabele die in een codeblok is gedeclareerd, bestaat tot het einde van dat codeblok.
  • Variabelen die methodeargumenten zijn, bestaan ​​tot het einde van de methode.
  • Klasse-/objectvariabelen bestaan ​​gedurende de levensduur van het bevattende object. Hun zichtbaarheid wordt gereguleerd door speciale toegangsmodificatoren.
  • Statische klassevariabelen bestaan ​​de hele tijd dat het programma draait. Hun zichtbaarheid wordt ook bepaald door toegangsmodificatoren.

Bereik op methodeniveau

Elke variabele die in een methode is gedeclareerd, inclusief argumenten, is buiten die methode niet toegankelijk. Alle variabelen die binnen methoden zijn gedeclareerd, zijn zichtbaar vanaf het begin van hun declaratie tot het einde van de methode. Hier is een voorbeeld van het bereik van de methodevariabele:

public class JScopeTest1 {


   public static void main(String[] args) {

       System.out.println(myMethod(5));
       System.out.println(myMethod(17));

   }
   public static int  myMethod(int arg) {
       int secondArg = 100; //local method variable
       return secondArg + arg;
   }
}
Hier hebben we secondArg , een lokale variabele of methodeargument. We kunnen deze variabele niet gebruiken buiten de methode myMethod of voordat deze werd gedeclareerd. Als een variabele een functieargument is, is deze zichtbaar in de hele body van deze methode. In het bovenstaande voorbeeld hebben we twee van dergelijke argumenten: arg in myMethod en args in main method.

Bereik op klasseniveau

Bereik op klasseniveau (instantievariabelen) — elke variabele die in een klasse wordt gedeclareerd, is beschikbaar voor alle methoden van die klasse. Afhankelijk van de toegangsmodificator (dwz openbaar of privé), is het soms toegankelijk buiten de klas. Dus als een variabele een klassevariabele is, dan is hij gebonden aan een specifiek object en bestaat hij zolang er een object van deze klasse is. Als er geen object is, is er geen kopie van de variabele. De variabele is zichtbaar vanuit alle methoden van de klasse, ongeacht of ze ervoor of erna gedeclareerd zijn. Elk object heeft zijn eigen variabele onafhankelijk van andere objecten. Toegang tot een variabele via statische methoden is niet mogelijk.

Codevoorbeeld


public class Student {
   
//class level variables
   public String surname;
   String name;
   String secondName;
   private Long birthday; // Long instead of long is used by Gson/Jackson json parsers and various orm databases

   public Student(String surname, String name, String secondName, Date birthday ){
       this.surname = surname;
       this.name = name;
       this.secondName = secondName;
       this.birthday = birthday == null ? 0 : birthday.getTime();
   }

   @Override
   public int hashCode(){
       //TODO: check for nulls
       //return surname.hashCode() ^ name.hashCode() ^ secondName.hashCode() ^ (birthday.hashCode());
       return (surname + name + secondName + birthday).hashCode();
   }
   @Override
   public boolean equals(Object other_) {
       Student other = (Student)other_;
       return (surname == null || surname.equals(other.surname) )
               && (name == null || name.equals(other.name))
               && (secondName == null || secondName.equals(other.secondName))
               && (birthday == null || birthday.equals(other.birthday));
   }
}
Surname , name , secondName en birthday zijn instantievariabelen.

Bereik blokkeren

Als een variabele in een codeblok is gedefinieerd/gedeclareerd, bestaat deze tot het einde van dat codeblok. Meestal bestaan ​​dergelijke variabelen tussen de accolades waarin ze zijn gedefinieerd. Heel vaak kan blokbereik een lusvariabele zijn. Een variabele die is gedeclareerd in een for- lusvoorwaarde is niet toegankelijk buiten de lus, tenzij u deze van tevoren hebt gedefinieerd.

public class JScopeTest2 {
   public static void main(String[] args) {
       for (int i = 0; i < 10; i++) {
           int sum = 0;
           sum = sum + i;
       }
      
       int sum = 1;
       System.out.println(sum);
   }
}
Zowel de eerste som- als de i-variabelen worden binnen de lus gedeclareerd en bestaan ​​niet buiten deze lus. De tweede som werd echter buiten de lus gedeclareerd, dus deze specifieke variabele wordt afgedrukt.

Statische variabelen

Als een variabele als statisch wordt gedeclareerd (gemarkeerd met het statische sleutelwoord), dan bestaat deze zolang zijn klasse bestaat. Doorgaans laadt de JVM een klasse in het geheugen bij het eerste gebruik, wanneer statische variabelen worden geïnitialiseerd.

import java.util.Date;

public class Student {
   public static int today = 2022;
   String surname;
   String name;
   String secondName;
   Long birthday; // Long instead of long is used by Gson/Jackson json parsers and various orm databases

   public Student(String surname, String name, String secondName, Date birthday ){
       this.surname = surname;
       this.name = name;
       this.secondName = secondName;
       this.birthday = birthday == null ? 0 : birthday.getTime();
   }

 
   public static void main(String[] args) {
       System.out.println(today);
   }

}
U moet geen nieuwe instantie van de klasse Student maken om de variabele static today te gebruiken . Hier wordt "2022" afgedrukt.

Toegang tot modificaties

Java heeft 4 toegangsmodificaties om de toegang tot de methode of variabele te beperken. Je kunt ze binnen klassen gebruiken, niet binnen methoden.
  • private is de meest beperkende modifier. Het beperkt de toegang tot methoden en variabelen tot de klasse waarin ze zijn gedeclareerd. Als het niet nodig is om bepaalde methoden of variabelen buiten de klasse te gebruiken, gebruik dan private. Klassevariabelen zijn meestal privé in Java.

  • Als er geen toegangsmodificator is opgegeven, accepteert de methode of variabele de standaardmodifier . standaard staat alleen toegang toe vanuit het huidige pakket.

  • beschermde modifier geeft alleen toegang tot een methode of variabele vanuit het huidige pakket, tenzij er toegang toe wordt verkregen via een onderliggende klasse buiten het pakket.

  • public is de minst beperkende modifier. Hiermee heb je niet alleen toegang tot een klasse, methode of variabele vanuit de klasse waarin ze zijn gedeclareerd, maar ook van buitenaf. Deze modifier wordt heel vaak gebruikt.