Java Language
Модификаторы без доступа
Поиск…
Вступление
Модификаторы без доступа не изменяют доступность переменных и методов, но они предоставляют им особые свойства .
окончательный
final
в Java может относиться к переменным, методам и классам. Существует три простых правила:
- конечная переменная не может быть переназначена
- окончательный метод нельзя переоценить
- окончательный класс не может быть расширен
Обычаи
Хорошая практика программирования
Некоторые разработчики считают хорошей практикой отмечать переменную final, когда можете. Если у вас есть переменная, которая не должна быть изменена, вы должны отметить ее окончательную.
Важное использование final
ключевого слова if для параметров метода. Если вы хотите подчеркнуть, что метод не меняет свои входные параметры, пометьте свойства как final.
public int sumup(final List<Integer> ints);
Это подчеркивает, что метод sumup
не собирается изменять ints
.
Доступ к внутреннему классу
Если ваш анонимный внутренний класс хочет получить доступ к переменной, переменная должна быть отмечена final
public IPrintName printName(){
String name;
return new IPrintName(){
@Override
public void printName(){
System.out.println(name);
}
};
}
Этот класс не компилируется, поскольку name
переменной не является окончательным.
Эффективно конечные переменные являются исключением. Это локальные переменные, которые записываются только один раз и поэтому могут быть сделаны окончательными. Эффективно конечные переменные можно получить и из классов анонимуса.
final static
переменная
Несмотря на то, что приведенный ниже код полностью легален, когда final
переменная foo
не является static
, в случае static
она не будет компилироваться:
class TestFinal {
private final static List foo;
public Test() {
foo = new ArrayList();
}
}
Причина в том, что, повторим еще раз, конечная переменная не может быть переназначена . Поскольку foo
является статическим, он разделяется между всеми экземплярами класса TestFinal
. Когда создается новый экземпляр класса TestFinal
, его конструктор вызывается и, следовательно, foo получает переназначение, компилятор которого не разрешает. Правильный способ инициализации переменной foo
в этом случае:
class TestFinal {
private static final List foo = new ArrayList();
//..
}
или с помощью статического инициализатора:
class TestFinal {
private static final List foo;
static {
foo = new ArrayList();
}
//..
}
final
методы полезны, когда базовый класс реализует некоторые важные функции, которые производный класс не должен изменять. Они также быстрее, чем не конечные методы, потому что нет никакой концепции виртуальной таблицы.
Все классы-оболочки в Java являются окончательными, например Integer
, Long
и т. Д. Создатели этих классов не хотели, чтобы кто-либо мог, например, расширить Integer в свой класс и изменить основное поведение класса Integer. Одним из требований к созданию неизменяемого класса является то, что подклассы не могут переопределять методы. Самый простой способ сделать это - объявить класс final
.
летучий
Модификатор volatile
используется в многопоточном программировании. Если вы объявляете поле volatile
это сигнал потокам, который должен прочитать последнее значение, а не локально кэшированное. Кроме того, volatile
чтения и записи гарантированно являются атомарными (доступ к volatile
long
или double
не является атомарным), что позволяет избежать некоторых ошибок чтения / записи между несколькими потоками.
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;
}
}
статический
static
ключевое слово используется для класса, метода или поля, чтобы заставить их работать независимо от любого экземпляра класса.
- Статические поля являются общими для всех экземпляров класса. Им не нужен экземпляр для доступа к ним.
- Статические методы могут выполняться без экземпляра класса, в котором они находятся. Однако они могут получить доступ только к статическим полям этого класса.
- Статические классы могут быть объявлены внутри других классов. Им не нужен экземпляр класса, в котором они должны быть созданы.
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
Аннотация
Абстракция - это процесс скрытия деталей реализации и отображения пользователю только функциональных возможностей. Абстрактный класс никогда не может быть создан. Если класс объявлен как абстрактный, единственной целью является расширение класса.
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");
}
}
синхронизированный
Синхронизированный модификатор используется для управления доступом определенного метода или блока несколькими потоками. Только один поток может входить в метод или блок, который объявляется как синхронизированный. синхронизированное ключевое слово работает на внутренней блокировке объекта, в случае синхронного метода блокировка текущих объектов и статический метод использует объект класса. Любой поток, пытающийся выполнить синхронизированный блок, должен сначала получить блокировку объекта.
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();
}
}
преходящий
Переменная, объявленная как переходная, не будет сериализована во время сериализации объекта.
public transient int limit = 55; // will not persist
public int b; // will persist
strictfp
Для вычисления с плавающей запятой используется модификатор strictfp. Этот модификатор делает переменную с плавающей запятой более согласованной на нескольких платформах и гарантирует, что все вычисления с плавающей запятой выполняются в соответствии со стандартами IEEE 754, чтобы избежать ошибок вычисления (ошибки округления), переполнения и переполнения как на 32-битной, так и на 64-битной архитектуре. Это нельзя применить к абстрактным методам, переменным или конструкторам.
// strictfp keyword can be applied on methods, classes and interfaces.
strictfp class A{}
strictfp interface M{}
class A{
strictfp void m(){}
}