Java Language
Modyfikatory niedostępne
Szukaj…
Wprowadzenie
Modyfikatory niedostępne nie zmieniają dostępności zmiennych i metod, ale zapewniają im specjalne właściwości .
finał
final
w Javie może odnosić się do zmiennych, metod i klas. Istnieją trzy proste zasady:
- końcowej zmiennej nie można przypisać ponownie
- ostatecznej metody nie można zastąpić
- klasa końcowa nie może być przedłużona
Zastosowania
Dobra praktyka programowania
Niektórzy programiści uważają, że dobrą praktyką jest oznaczanie zmiennej końcowej, kiedy jest to możliwe. Jeśli masz zmienną, której nie należy zmieniać, oznacz ją jako ostateczną.
Ważne użycie final
słowa kluczowego, jeśli chodzi o parametry metody. Jeśli chcesz podkreślić, że metoda nie zmienia parametrów wejściowych, zaznacz właściwości jako końcowe.
public int sumup(final List<Integer> ints);
Podkreśla to, że metoda sumup
nie zmieni ints
.
Dostęp do klasy wewnętrznej
Jeśli twoja anonimowa klasa wewnętrzna chce uzyskać dostęp do zmiennej, zmienna powinna być oznaczona jako final
public IPrintName printName(){
String name;
return new IPrintName(){
@Override
public void printName(){
System.out.println(name);
}
};
}
Ta klasa nie kompiluje się, ponieważ name
zmiennej nie jest ostateczna.
Wyjątkowo skuteczne są zmienne końcowe. Są to zmienne lokalne, które są zapisywane tylko raz i dlatego mogą być ostateczne. Do efektywnych zmiennych końcowych można również uzyskać dostęp z klas anonimowych.
final static
zmienna final static
Mimo że poniższy kod jest całkowicie legalny, gdy final
zmienna foo
nie jest static
, w przypadku static
nie będzie się kompilować:
class TestFinal {
private final static List foo;
public Test() {
foo = new ArrayList();
}
}
Powodem jest to, powtórzmy jeszcze raz, ostatecznej zmiennej nie można przypisać ponownie . Ponieważ foo
jest statyczny, jest współużytkowany przez wszystkie instancje klasy TestFinal
. Kiedy TestFinal
jest nowa instancja klasy TestFinal
, wywoływany jest jej konstruktor, dlatego foo zostaje ponownie przypisany, który kompilator nie zezwala. Prawidłowym sposobem na zainicjowanie zmiennej foo
w tym przypadku jest:
class TestFinal {
private static final List foo = new ArrayList();
//..
}
lub za pomocą inicjatora statycznego:
class TestFinal {
private static final List foo;
static {
foo = new ArrayList();
}
//..
}
metody final
są przydatne, gdy klasa podstawowa implementuje ważną funkcję, której klasa pochodna nie powinna zmieniać. Są również szybsze niż metody nie-końcowe, ponieważ nie ma w nich pojęcia o wirtualnej tabeli.
Wszystkie klasy otoki w Javie są ostateczne, takie jak Integer
, Long
itp. Twórcy tych klas nie chcieli, aby ktokolwiek mógł np. Rozszerzyć Integer na własną klasę i zmienić podstawowe zachowanie klasy Integer. Jednym z wymagań, aby klasa była niezmienna, jest to, że podklasy nie mogą zastępować metod. Najprostszym sposobem na to jest zadeklarowanie klasy jako final
.
lotny
volatile
modyfikator jest stosowany w programowaniu wielowątkowym. Jeśli zadeklarujesz pole jako volatile
, jest to sygnał dla wątków, że muszą odczytać najnowszą wartość, a nie lokalnie buforowaną. Co więcej, volatile
odczyty i zapisy są gwarantowane jako atomowe (dostęp do volatile
long
lub double
nie jest atomowy), dzięki czemu unika się pewnych błędów odczytu / zapisu między wieloma wątkami.
public class MyRunnable implements Runnable
{
private volatile boolean active;
public void run(){ // run is called in one thread
active = true;
while (active){
// some code here
}
}
public void stop(){ // stop() is called from another thread
active = false;
}
}
statyczny
static
słowo kluczowe jest używane w klasie, metodzie lub polu, aby działały niezależnie od dowolnego wystąpienia klasy.
- Pola statyczne są wspólne dla wszystkich instancji klasy. Nie potrzebują instancji, aby uzyskać do nich dostęp.
- Metody statyczne można uruchamiać bez wystąpienia klasy, w której się znajdują. Mogą jednak uzyskiwać dostęp tylko do pól statycznych tej klasy.
- Klasy statyczne mogą być deklarowane wewnątrz innych klas. Nie potrzebują wystąpienia instancji klasy, w której są tworzone.
public class TestStatic
{
static int staticVariable;
static {
// This block of code is run when the class first loads
staticVariable = 11;
}
int nonStaticVariable = 5;
static void doSomething() {
// We can access static variables from static methods
staticVariable = 10;
}
void add() {
// We can access both static and non-static variables from non-static methods
nonStaticVariable += staticVariable;
}
static class StaticInnerClass {
int number;
public StaticInnerClass(int _number) {
number = _number;
}
void doSomething() {
// We can access number and staticVariable, but not nonStaticVariable
number += staticVariable;
}
int getNumber() {
return number;
}
}
}
// Static fields and methods
TestStatic object1 = new TestStatic();
System.out.println(object1.staticVariable); // 11
System.out.println(TestStatic.staticVariable); // 11
TestStatic.doSomething();
TestStatic object2 = new TestStatic();
System.out.println(object1.staticVariable); // 10
System.out.println(object2.staticVariable); // 10
System.out.println(TestStatic.staticVariable); // 10
object1.add();
System.out.println(object1.nonStaticVariable); // 15
System.out.println(object2.nonStaticVariable); // 10
// Static inner classes
StaticInnerClass object3 = new TestStatic.StaticInnerClass(100);
StaticInnerClass object4 = new TestStatic.StaticInnerClass(200);
System.out.println(object3.getNumber()); // 100
System.out.println(object4.getNumber()); // 200
object3.doSomething();
System.out.println(object3.getNumber()); // 110
System.out.println(object4.getNumber()); // 200
abstrakcyjny
Abstrakcja to proces ukrywania szczegółów implementacji i pokazywania użytkownikowi tylko funkcjonalności. Klasa abstrakcyjna nigdy nie może zostać utworzona. Jeśli klasa zostanie zadeklarowana jako abstrakcyjna, jedynym celem jest rozszerzenie klasy.
abstract class Car
{
abstract void tagLine();
}
class Honda extends Car
{
void tagLine()
{
System.out.println("Start Something Special");
}
}
class Toyota extends Car
{
void tagLine()
{
System.out.println("Drive Your Dreams");
}
}
zsynchronizowany
Zsynchronizowany modyfikator służy do kontrolowania dostępu do określonej metody lub bloku za pomocą wielu wątków. Tylko jeden wątek może wejść do metody lub bloku, który jest zadeklarowany jako zsynchronizowany. Zsynchronizowane słowo kluczowe działa na wewnętrzną blokadę obiektu, w przypadku metody zsynchronizowanej blokada bieżących obiektów, a metoda statyczna używa obiektu klasy. Każdy wątek próbujący wykonać zsynchronizowany blok musi najpierw uzyskać blokadę obiektu.
class Shared
{
int i;
synchronized void SharedMethod()
{
Thread t = Thread.currentThread();
for(int i = 0; i <= 1000; i++)
{
System.out.println(t.getName()+" : "+i);
}
}
void SharedMethod2()
{
synchronized (this)
{
System.out.println("Thais access to currect object is synchronize "+this);
}
}
}
public class ThreadsInJava
{
public static void main(String[] args)
{
final Shared s1 = new Shared();
Thread t1 = new Thread("Thread - 1")
{
@Override
public void run()
{
s1.SharedMethod();
}
};
Thread t2 = new Thread("Thread - 2")
{
@Override
public void run()
{
s1.SharedMethod();
}
};
t1.start();
t2.start();
}
}
przemijający
Zmienna zadeklarowana jako przejściowa nie będzie serializowana podczas serializacji obiektu.
public transient int limit = 55; // will not persist
public int b; // will persist
strictfp
modyfikator strictfp służy do obliczeń zmiennoprzecinkowych. Ten modyfikator sprawia, że zmienna zmiennoprzecinkowa jest bardziej spójna na wielu platformach i zapewnia, że wszystkie obliczenia zmiennoprzecinkowe są wykonywane zgodnie ze standardami IEEE 754, aby uniknąć błędów obliczeniowych (błędów zaokrąglania), przelewów i niedopełnień w architekturze 32-bitowej i 64-bitowej. Nie można tego zastosować do metod abstrakcyjnych, zmiennych lub konstruktorów.
// strictfp keyword can be applied on methods, classes and interfaces.
strictfp class A{}
strictfp interface M{}
class A{
strictfp void m(){}
}