Java-модификаторы. Модификаторы в Java: static, final, abstract, synchronized, transient, volatile Модификатор доступа protected означает

Язык Java предоставляет множество модификаторов, разделенных на следующие категории:

  • модификатор доступа
  • Модификатор Non-доступа

Модификатор используется для определения класса, метода или переменной, как правило, на переднем крае заявления. Через следующий пример для иллюстрации:

Public class className { // ... } private boolean myFlag; static final double weeks = 9.5; protected static final int BOXWIDTH = 42; public static void main(String arguments) { // 方法体 }

Модификатор контроля доступа

Java, вы можете использовать символы контроля доступа для защиты доступа к классам, переменных, методов и конструкторов. Java поддерживает четыре различных прав доступа.

По умолчанию, также известный как значение по умолчанию, видимый в том же самом пакете, не используют какие - либо модификатор.

Частный, чтобы указан частный модификатор, видимый в пределах того же класса.

Есть, для того, чтобы указать общий модификатор, видимый для всех классов.

Защищенный, в защищенный модификатор определяет, что для всех классов и подклассов в пределах того же пакета видимой.

Модификатор доступа по умолчанию - не использовать какие-либо ключевые слова

Используйте переменные и методы, объявленные в модификатором доступа по умолчанию для класса в пределах того же пакета видна. Интерфейс где переменные неявно объявлен как публичным статическим финале, и интерфейс, где метод доступа по умолчанию для публики.

Заявление в следующем примере, переменные и методы не могут использовать любой модификатор.

String version = "1.5.1"; boolean processOrder() { return true; }

Частный доступ модификатор -private

Частный модификатор доступа, является самым жестким уровень доступа, он объявлен как частных методов, переменных, и принадлежит к классу конструктора могут быть доступны только, а классы и интерфейсы не могут быть объявлены закрытыми.

Переменные, объявленные в качестве частного типа доступа могут быть доступны только за пределами класса через класс метода общественного геттерного.

Модификатор Частный доступ используется в основном для класса защиты деталей реализации и данных за классом.

Следующие классы используют частный модификатор доступа:

Public class Logger { private String format; public String getFormat() { return this.format; } public void setFormat(String format) { this.format = format; } }

Пример, переменный формат класса Logger является частной переменной, так что другие классы не могут непосредственно получить и установить значение переменной. Для того, чтобы иметь возможность работать с другой переменной класса определяет два открытых метода: GetFormat () (формат возвращаемого значения) и SetFormat (String) (настройка формата)

Открытый доступ модификатор -публичный

Он объявлен в качестве общественных классов, методов, конструкторов, и интерфейсы могут быть любой другой тип доступа.

Если несколько взаимных визитов общественных классов в разных пакетах, вам нужно импортировать соответствующий пакет общественного класса постоянно находится. Поскольку наследование классов, класс всех общедоступных методов и переменных могут быть унаследованы его подклассов.

Следующие функции используют контроль доступа общественности:

Public static void main(String arguments) { // ... }

Метод главной Java программы () должен быть установлен в общественных местах, в противном случае, Java интерпретатор не сможет запустить класс.

Защищенные модификаторы доступа охраняемыми

Объявлена ​​как защищенные переменные, методы и конструкторы в том же пакете может быть любой другой тип доступа, и могут быть доступны в различных пакетах подклассов.

Защищенный модификатор доступа не могут быть изменены классы и интерфейсы, методы и переменные-члены могут быть объявлены как защищенные, но переменные и методы-члены интерфейсов не могут быть объявлены защищенными.

модификатор Подклассы могут получить доступ объявлен Защищенные методы и переменные, так что мы можем защитить несвязанные классы, используя эти методы и переменные.

Следующий родительский класс использует защищенный модификатор доступа, подклассов переопределить метод openSpeaker () родительского класса.

Class AudioPlayer { protected boolean openSpeaker(Speaker sp) { // 实现细节 } } class StreamingAudioPlayer { boolean openSpeaker(Speaker sp) { // 实现细节 } }

Если метод openSpeaker () объявлен как частный, то в дополнение к классу AudioPlayer не может получить доступ к методу. Если openSpeaker () объявлена ​​как публичная, то все классы имеют возможность доступа к методу. Если мы хотим, чтобы сделать процесс видимым для подклассов класса, то метод объявлен как защищенный.

Контроль доступа и наследование

Обратите внимание на следующие методы унаследовали правила:

    Родительский класс объявлен как публичные методы в подклассе также должен быть публичным.

    Класс Родитель объявлен как защищенный метод в подклассе или объявлены как защищенные, либо объявлены публично. Вы не можете быть объявлены закрытыми.

    Родительский класс объявлен как частный метод не может быть унаследован.

Модификатор Non-доступа

Для того, чтобы достичь ряда других функций, Java, также предоставляет ряд модификаторов без доступа.

статический модификатор используется для создания методов класса и переменные класса.

Окончательный модификатор, используемый для украшения классов, методов и переменных, конечное модифицированный класс не может быть унаследован, модифицированный метод класса не может быть унаследован переопределены, модифицированные переменные константы, не могут быть изменены.

Абстрактный модификатор используется для создания абстрактных классов и абстрактных методов.

Синхронное и летучие модификаторы, в основном для потоков программирования.

Статический модификатор

    Статические переменные:

    Статическая используется ключевое слово, чтобы объявить статические переменные, не зависящие от объекта, независимо от того, сколько объектов экземпляра класса, это только одна копия статической переменной. Статические переменные также известны как переменные класса. Локальные переменные не могут быть объявлены как статические переменные.

    Статические методы:

    Статический ключевое слово используется для объявления объект не зависит от статического метода. Статические методы не могут использовать не статический класс переменных. Статический метод, чтобы получить данные из списка параметров, а затем рассчитать данные.

Доступ к переменным класса и методы могут быть использованы непосредственно classname.variablename и classname.methodname доступа.

В следующем примере, статический модификатор используется для создания методов класса и переменные класса.

Public class InstanceCounter { private static int numInstances = 0; protected static int getCount() { return numInstances; } private static void addInstance() { numInstances++; } InstanceCounter() { InstanceCounter.addInstance(); } public static void main(String arguments) { System.out.println("Starting with " + InstanceCounter.getCount() + " instances"); for (int i = 0; i < 500; ++i){ new InstanceCounter(); } System.out.println("Created " + InstanceCounter.getCount() + " instances"); } }

Примеры приведенных выше результатов операции редактирования следующим образом:

Started with 0 instances Created 500 instances

Окончательный классификатор

Конечные переменные:

Окончательные переменные могут быть явно инициализированы и инициализируется только один раз. Справочник объявляется как конечные объекты не могут указывать на другой объект. Но конечная цель, где данные могут быть изменены. Это конечная ссылка на объект не может быть изменен, но значение которого может быть изменено.

Окончательный модификатор обычно используется вместе, чтобы создать статическую константу класса модификатора.

Public class Test{ final int value = 10; // 下面是声明常量的实例 public static final int BOXWIDTH = 6; static final String TITLE = "Manager"; public void changeValue(){ value = 12; //将输出一个错误 } }

Окончательный метод

Методы конечный класс наследуются подклассами, но не может изменять подклассы.

Основная цель метода заключается в том, чтобы предотвратить окончательное заявление этого метода изменяется.

Как будет показано ниже, с использованием конечных методов модификаторов декларации.

Public class Test{ public final void changeName(){ // 方法体 } }

Окончательная категория

Конечные классы не могут быть унаследованы, ни один класс может наследовать любой из характеристик конечного класса.

Public final class Test { // 类体 }

Абстрактный модификатор

Абстрактный класс:

Абстрактный класс не может быть использован для создания экземпляра объекта, единственной целью заявления является абстрактным классом для будущего расширения этого класса.

Класс не может быть изменен абстрактным и окончательным. Если класс содержит абстрактные методы, класс должен быть объявлен как абстрактный класс, в противном случае, ошибка компилятора.

Абстрактный класс может содержать абстрактные методы и не абстрактные методы.

Abstract class Caravan{ private double price; private String model; private String year; public abstract void goFast(); //抽象方法 public abstract void changeColor(); }

Абстрактный метод

Ни один метод не является абстрактным реализация метода, конкретная реализация метода предоставляемых подклассов. Абстрактные методы не могут быть объявлены в качестве окончательного и строгим.

Любой подкласс наследует абстрактный класс должен реализовать все абстрактные методы родительского класса, если подкласс не является абстрактным классом.

Если класс содержит ряд абстрактных методов, класс должен быть объявлен как абстрактный класс. Абстрактный класс не может содержать абстрактные методы.

Абстрактный объявление метода заканчивается точкой с запятой, например: общественный абстрактный образец ();

Public abstract class SuperClass{ abstract void m(); //抽象方法 } class SubClass extends SuperClass{ //实现抽象方法 void m(){ ......... } }

Синхронное модификатор

Метод Синхронное ключевое слово, чтобы объявить то же время только один доступ нить. Синхронное модификатор может быть применен к четырем модификаторов доступа.

Public synchronized void showDetails(){ ....... }

Переходный модификатор

Сериализованная объект содержит модифицированные переходными переменными экземпляра виртуальной машины Java (JVM), чтобы пропустить эту конкретную переменную.

Модификатор включен в определение переменных заявления для предварительной обработки классов типов данных и переменных.

Public transient int limit = 55; // will not persist public int b; // will persist

Летучие Модификаторы

Летучие модифицированная переменная-член каждый раз при обращении к нему потоки вынуждены перечитать значение переменной-члена из совместно используемой памяти. Кроме того, когда изменения переменных членов, поток вынужден изменить значение записывается обратно в общей памяти. Так что в любое время, две разные темы всегда видят одинаковое значение переменной-члена.

Public class MyRunnable implements Runnable { private volatile boolean active; public void run() { active = true; while (active) // 第一行 { // 代码 } } public void stop() { active = false; // 第二行 } }

При нормальных обстоятельствах, поток вызывает метод () Run (в Runnable открытом потоке) в другом потоке вызовов остановить () метод. Если активное значение в первой строке буфера используется, во втором ряду , когда активный цикл ложна не останавливается.

Тем не менее, приведенный выше код, мы используем модифицированный летучий активный, поэтому цикл остановится.

Мы поговорим о модификаторах: какие бывают модификаторы, области видимости, модификаторы для классов, полей, методов. Думаю, будет не скучно.

Модификаторы в Java – это ключевые слова, которые придают классу, полю класса или методу определенные свойства.

Для обозначения видимости класса его методов и полей есть 4 модификатора доступа:

  • private члены класса доступны только внутри класса;
  • package-private или default (по умолчанию) члены класса видны внутри пакета;
  • protected члены класса доступны внутри пакета и в классах-наследниках;
  • public члены класса доступны всем.

Если Вы помните , то в конце, когда мы уже импортировали класс Cat, у нас все равно была ошибка компиляции.

Все дело в том, что мы не прописали никаких модификаторов доступа к нашим полям и методам и они имеют свойство по умолчанию (члены класса видны внутри пакета). Чтобы исправить ошибку компиляции для нашего кода и наконец то запустить его, нужно сделать наш конструктор и методы public. Тогда их можно будет вызывать с других пакетов.

Вы можете начать задаваться вопросом: а для чего все это нужно? Почему не сделать видимость кода из любого пакета или класса, а нужно разграничить доступ? Эти вопросы сами пропадут, когда придет время писать сложные и громоздкие проекты. Сейчас, когда мы пишем приложения, у которых функционал ограничен одним или двумя классами, то смысла что либо ограничить вроде как не видно.

Представьте, что у Вас есть класс который отображает объект некоего продукта. Например машина. У машины может быть цена. Вы создали поле цена и еще множество других полей, кучу методов которые отвечают за функционал. Все вроде хорошо. Ваш класс машина является частью огромного проекта и все довольны. Но допустим, что кто-то по ошибке или специально создал экземпляр класса автомобиль и поставил отрицательную цену. Разве может товар иметь отрицательную цену? Это очень примитивный пример и вряд ли такое может случиться в реальной жизни, но думаю, идея понятна. Иногда нужно дать доступ не напрямую, а через определенные методы. Может быть, что код отвечает за функционал другого кода, и Вы не хотите, чтобы кто-то изменял и редактировал часть Вашего. Для этого всего и есть ограничение доступа.

Модификатор доступа у конструкторов, методов и полей может быть любой. Класс может быть только либо public, либо default, причем в одном файле может находиться только один public класс.

Пока об модификаторах доступа будет достаточно. В статье «Объектно ориентированное программирование» мы о них поговорим подробнее, а сейчас давайте поговорим о других модификаторах которых, к стати, немало.

Сейчас на очереди модификатор static . Его можно применять перед методом, полем и даже классом, когда хотим объявить вложенный класс. В Java можно писать классы внутри других классов и если модификатор перед классом внутри класса static, то такой класс называют вложенным, если другой модификатор или по умолчанию, то такой класс называется внутренним. О вложенных и внутренних классах будет отдельная статья, поскольку там не все так просто.

static модификатор перед методом или полем говорит о том, что они не принадлежат к экземпляру данного класса. Что это означает для нас? Когда мы описали поле класса или метод как static, его можно вызвать без использования экземпляра класса. То есть вместо такой конструкции: Cat cat = new Cat(); cat.method(), можно написать просто Cat.method(). При условии, что метод объявлен как static. Статические переменные едины для всех объектов класса. У них одна ссылка.

    public class Modificators {

    static int anotherStaticField = 5 ;

    public static void myStaticMethod() {

    someField = "My field" ;

    //nonStaticField = ""; ошибка компиляции

    //нельзя использовать нестатические поля

    //в статических методах

    public void myNonStaticMethod() {

    anotherStaticField = 4 ; //ститические поля можно использовать

    //в нестатических методах

    //main метод тоже имеет модификатор static

    new Modificators() .myNonStaticMethod () ;

    Modificators.myStaticMethod () ; //вызов статических методов и полей

    //через имяКласса.метод

Еще одно важное замечание, которое нужно сказать по поводу static модификаторов: статические поля инициализируются во время загрузки класса. Часто в разного рода тестах по Java можно встретить такой код:

Вопрос: что будет выведено на консоль? Нужно помнить, что static блок будет выведен первым при любом раскладе. Далее будет идти блок по умолчанию. Далее смотрите на скрин консоли:

Следующий модификатор, который мы рассмотрим будет final.

Думаю, слово final говорит само за себя. Применяя final модификатор Вы говорите, что поля не могут быть изменены, методы переопределены, а классы нельзя наследовать (о наследовании будет отдельная статья). Этот модификатор применяется только к классам, методам и переменным (также и к локальным переменным).

С модификатором final к методам и классам мы будем говорить в статье ООП.

Далее пойдут модификаторы, которые новичкам или читающим данный цикл статей с нуля будут не очень понятными. И хотя я пока не смогу Вам все объяснить (в силу того, что Вы не знаете сопутствующего материала), все же советую просто ознакомиться с ними. Когда придет время использования данных модификаторов, Вы уже будете понимать большинство терминов используемых ниже.

Модификатор synchronized — говорит о том, что метод может быть использован только одним потоком одновременно. Хотя, возможно, это Вам ни о чем не говорит, полезность этого модификатора будет видно, когда мы будем изучать многопоточность.

Модификатор transient — говорит о том, что во время сериализации объекта некоторое поле нужно игнорировать. Как правило, такие поля хранят промежуточные значения.

Модификатор volatile — используется при многопоточности. Когда поле с модификатором volatile будет использоваться и изменяться несколькими потоками, данный модификатор гарантирует, что поле будет изменяться по очереди и путаницы с ним не возникнет.

Модификатор native перед объявлением метода указывает что метод написан на другом языке программирования. Обычно на языке C.

Модификатор strictfp — Обеспечивает выполнение операций над числами типа float и double (с плавающей запятой) по стандарту IEEE 754. Или говоря проще, гарантирует что в пределах метода результаты вычислений будут одинаковыми на всех платформах.

Я еще не говорил о модификаторе abstract . О нем скажу вкратце, так как без знаний основ объектно ориентированного программирования говорить о нем не вижу смысла.

Класс, который имеет модификатор abstract не может создать экземпляр. Единственная цель для него быть расширенным. Класс abstract может содержать как абстрактные методы, а также и обычные.

Подробнее о модификаторе abstract будем говорить в статье ООП.

На этом можно и закончить статью о модификаторах. Многое о них не было сказано. Но это из-за того, что у нас еще нет понятий ООП. Через несколько статей, мы дополним знания о модификаторах и заполним пробелы.

Которые Вы добавляете при инициализации для изменения значений. Язык Java имеет широкий спектр модификаторов, основные из них:

  • модификаторы доступа;
  • модификаторы класса, метода, переменной и потока, используемые не для доступа.

Чтобы использовать модификатор в Java, нужно включить его ключевое слово в определение класса, метода или переменной. Модификатор должен быть впереди остальной части оператора, как показано в следующих примерах:

Public class className { // ... } private boolean myFlag; static final double weeks = 9.5; protected static final int BOXWIDTH = 42; public static void main(String arguments) { // тело метода }

Модификаторы доступа

Java предоставляет ряд модификаторов доступа, чтобы задать уровни доступа для классов, переменных, методов и конструкторов. Существует четыре доступа:

  • Видимый в пакете (стоит по умолчанию и модификатор не требуются).
  • Видимый только для класса (private).
  • Видимый для всех (public).
  • Видимый для пакета и всех подклассов (protected).

Модификатор доступа по умолчанию - без ключевого слова

Модификатор доступа по умолчанию - означает, что мы явно не объявляем модификатор доступа в Java для класса, поля, метода и т.д.

Переменная или метод, объявленные без модификатора контроля доступа доступны для любого другого класса в том же пакете. Поля в интерфейсе неявно являются public, static, final, а методы в интерфейсе по умолчанию являются public.

Пример

Переменные и методы могут быть объявлены в Java без каких-либо модификаторов, как показано в следующем примере:

String version = "1.5.1"; boolean processOrder() { return true; }

Модификатор доступа private

Модификатор private - методы, переменные и конструкторы, которые объявлены как private в Java могут быть доступны только в пределах самого объявленного класса.

Модификатор доступа private является наиболее ограничивающим уровенем доступа. Класс и интерфейсы не могут быть private.

Переменные, объявленные как private, могут быть доступны вне класса, если получающие их открытые (public) методы присутствуют в классе (ниже смотрите пример и пояснения).

Использование модификатора private в Java является основным способом, чтобы скрыть данные.

Пример

Следующий класс использует контроль доступа private:

Public class Logger { private String format; public String getFormat() { return this.format; } public void setFormat(String format) { this.format = format; } }

Здесь переменная format класса Logger является private, так что нет никакого способа для других классов, чтобы получить и установить её значение напрямую.

Таким образом, чтобы эта переменная была доступна для всего, мы определили два открытых (public) метода: getFormat() , который возвращает значение format , и setFormat(String) , который устанавливает её значение.

Модификатор доступа public

Модификатор public - класс, метод, конструктор, интерфейс и т.д. объявленные как public могут быть доступны из любого другого класса. Поэтому поля, методы, блоки, объявленные внутри public класса могут быть доступны из любого класса, принадлежащего к "вселенной" Java.

Тем не менее, если к public классу в другом пакете мы пытаемся получить доступ, то public класс приходится импортировать.

Благодаря наследованию классов, в Java все публичные (public) методы и переменные класса наследуются его подклассами.

Пример

Следующая функция использует контроль доступа public:

Public static void main(String arguments) { // ... }

Метод main() должен быть публичным (public). В противном случае, он не может быть вызван с помощью java-интерпретатора, чтобы запустить класс.

Модификатор доступа protected

Модификатор protected - переменные, методы и конструкторы, которые объявляются как protected в суперклассе, могут быть доступны только для подклассов в другом пакете или для любого класса в пакете класса protected.

Модификатор доступа protected в Java не может быть применен к классу и интерфейсам. Методы и поля могут быть объявлены как protected, однако методы и поля в интерфейсе не могут быть объявлены как protected.

Доступ protected дает подклассу возможность использовать вспомогательный метод или переменную, предотвращая неродственный класс от попыток использовать их.

Пример

Следующий родительский класс использует контроля доступа protected, чтобы его дочерний класс переопределил метод openSpeaker() :

Class AudioPlayer { protected boolean openSpeaker(Speaker sp) { // детали реализации } } class StreamingAudioPlayer { boolean openSpeaker(Speaker sp) { // детали реализации } }

При этом, если мы определим метод openSpeaker() как protected, то он не будет доступен из любого другого класса, кроме AudioPlayer. Если мы определим его как public, то он станет доступным всем. Но наше намерение состоит в том, чтобы раскрыть этот метод только подклассу, вот почему мы использовали модификатор protected.

Правила контроля доступа и наследования

Следующие правила в Java применяются для унаследованных методов:

  • Методы, объявленные как public в суперклассе, также должны быть public во всех подклассах.
  • Методы, объявленные как protected в суперклассе, должны либо быть либо protected, либо public в подклассах; они не могут быть private.
  • Методы, объявленные как private для всех не наследуются, так что нет никакого правила для них.

Модификаторы класса, метода, переменной и потока, используемые не для доступа

Java предоставляет ряд модификаторов не для доступа, а для реализации многих других функциональных возможностей:

  • модификатор static применяется для создания методов и переменных класса;
  • модификатор final используется для завершения реализации классов, методов и переменных;
  • модификатор abstract необходим для создания абстрактных классов и методов;
  • модификаторы synchronized и volatile используются в Java для потоков.

Модификатор static

Модификатор static - применяется для создания методов и переменных класса.

Переменные static

Ключевое слово static используется для создания переменных, которые будут существовать независимо от каких-либо экземпляров, созданных для класса. Только одна копия переменной static в Java существует вне зависимости от количества экземпляров класса.

Статические переменные также известны как переменные класса. В Java локальные переменные не могут быть объявлены статическими (static).

Методы static

Ключевое слово static используется для создания методов, которые будут существовать независимо от каких-либо экземпляров, созданных для класса.

В Java статические методы или методы static не используют какие-либо переменные экземпляра любого объекта класса, они определены. Методы static принимают все данные из параметров и что-то из этих параметров вычисляется без ссылки на переменные.

Переменные и методы класса могут быть доступны с использованием имени класса, за которым следует точка и имя переменной или метода.

Пример

Модификатор static в Java используется для создания методов классов и переменных, как показано в следующем примере:

Public class InstanceCounter { private static int numInstances = 0; protected static int getCount() { return numInstances; } private static void addInstance() { numInstances++; } InstanceCounter() { InstanceCounter.addInstance(); } public static void main(String arguments) { System.out.println("Начиная с " + InstanceCounter.getCount() + " экземпляра"); for (int i = 0; i

Будет получен следующий результат:

Начиная с 0 экземпляра Создано 500 экземпляров

Модификатор final

Модификатор final - используется для завершения реализации классов, методов и переменных.

Переменные final

Переменная final может быть инициализирована только один раз. Ссылочная переменная, объявленная как final, никогда не может быть назначен для обозначения другого объекта.

Однако данные внутри объекта могут быть изменены. Таким образом, состояние объекта может быть изменено, но не ссылки.

С переменными в Java модификатор final часто используется со static, чтобы сделать константой переменную класса.

Пример

public class Test{ final int value = 10; // Ниже приведены примеры объявления констант: public static final int BOXWIDTH = 6; static final String TITLE = "Менеджер"; public void changeValue(){ value = 12; //будет получена ошибка } }

Методы final

Метод final не может быть переопределен любым подклассом. Как упоминалось ранее, в Java модификатор final предотвращает метод от изменений в подклассе.

Главным намерение сделать метод final будет то, что содержание метода не должно быть изменено стороне.

Пример

Объявление метода, использующего модификатор final в объявление класса, показано в следующем примере:

Public class Test{ public final void changeName(){ // тело метода } }

Класс final

Основная цель в Java использования класса объявленного в качестве final заключается в предотвращении класс от быть подклассом. Если класс помечается как final, то ни один класс не может наследовать любую функцию из класса final.

Пример

public final class Test { // тело класса }

Модификатор abstract

Модификатор abstract - используется для создания абстрактных классов и методов.

Класс abstract

Класс abstract не может создать экземпляр. Если класс объявлен как abstract, то единственная цель для него быть расширенным.

Класс не может быть одновременно abstract и final, так как класс final не может быть расширенным. Если класс содержит абстрактные методы, то он должен быть объявлен как abstract. В противном случае будет сгенерирована ошибка компиляции.

Класс abstract может содержать как абстрактные методы, а также и обычные.

Пример

abstract class Caravan{ private double price; private String model; private String year; public abstract void goFast(); //абстрактный метод public abstract void changeColor(); }

Метод abstract

Метод abstract является методом, объявленным с любой реализацией. Тело метода (реализация) обеспечивается подклассом. Методы abstract никогда не могут быть final или strict.

Любой класс, который расширяет абстрактный класс должен реализовать все абстрактные методы суперкласса, если подкласс не является абстрактным классом.

Если класс в Java содержит один или несколько абстрактных методов, то класс должен быть объявлен как abstract. Абстрактный класс не обязан содержать абстрактные методы.

Абстрактный метод заканчивается точкой с запятой. Пример: public abstract sample();

Пример

public abstract class SuperClass{ abstract void m(); //абстрактный метод } class SubClass extends SuperClass{ // реализует абстрактный метод void m(){ ......... } }

Модификатор synchronized

Модификатор synchronized

Ключевое слово synchronized используется для указания того, что метод может быть доступен только одним потоком одновременно. В Java модификатор synchronized может быть применен с любым из четырех модификаторов уровня доступа.

Пример

public synchronized void showDetails(){ ....... }

Модификатор transient

Переменная экземпляра отмеченная как transient указывает виртуальной машине Java (JVM), чтобы пропустить определённую переменную при сериализации объекта, содержащего её.

Этот модификатор включён в оператор, что создает переменную, предшествующего класса или типа данных переменной.

Пример

public transient int limit = 55; // не будет сохраняться public int b; // будет сохраняться

Модификатор volatile

Модификатор volatile - используются в Java для потоков.

В Java модификатор volatile используется, чтобы позволить знать JVM, что поток доступа к переменной всегда должен объединять свою собственную копию переменной с главной копией в памяти.

Доступ к переменной volatile синхронизирует все кэшированные скопированные переменные в оперативной памяти. Volatile может быть применен только к переменным экземпляра, которые имеют тип объект или private. Ссылка на объект volatile может быть null.

Пример

public class MyRunnable implements Runnable{ private volatile boolean active; public void run(){ active = true; while (active){ // линия 1 // здесь какой-нибудь код } } public void stop(){ active = false; // линия 2 } }

Как правило, run() вызывается в одном потоке (впервые начинаете использовать Runnable в Java), а stop() вызывается из другого потока. Если в линии 1 используется кэшированное значение active, то цикл не может остановиться, пока Вы не установите active false в линии 2.

В следующем уроке обсудим основные операторы, используемые в языке Java. Этот раздел даст Вам обзор того, как можно использовать их во время разработки приложения.

Привет! В сегодняшней лекции мы познакомимся с понятием «модификаторы доступа » и рассмотрим примеры работы с ними. Хотя слово «познакомимся» будет не совсем правильным: с большинством из них ты уже знаком по предыдущим лекциям. На всякий случай освежим в памяти главное. Модификаторы доступа - это чаще всего ключевые слова, которые регулируют уровень доступа к разным частям твоего кода. Почему «чаще всего»? Потому что один из них установлен по умолчанию и не обозначается ключевым словом:) Всего в Java есть четыре модификатора доступа. Перечислим их в порядке от самых строгих до самых «мягких»:

  • private;
  • protected;
  • default (package visible);
  • public.
Давай рассмотрим каждый из них, определимся, когда они могут нам пригодиться и приведем примеры:)

Модификатор private


Private - наиболее строгий модификатор доступа. Он ограничивает видимость данных и методов пределами одного класса. Этот модификатор тебе известен из лекции про геттеры и сеттеры. Помнишь этот пример? public class Cat { public String name; public int age; public int weight; public Cat (String name, int age, int weight) { this . name = name; this . age = age; this . weight = weight; } public Cat () { } public void sayMeow () { System. out. println ("Мяу!" ) ; } } public class Main { public static void main (String args) { Cat cat = new Cat () ; cat. name = "" ; cat. age = - 1000 ; cat. weight = 0 ; } } Мы рассматривали его в одной из статей раньше. Здесь мы допустили серьезную ошибку: открыли наши данные, в результате чего коллеги-программисты получили доступ напрямую к полям класса и изменению их значения. Более того, эти значения присваивались без проверок, в результате чего в нашей программе можно создать кота с возрастом -1000 лет, именем «» и весом 0. Для решения этой проблемы мы использовали геттеры и сеттеры , а также ограничили доступ к данным с помощью модификатора private . public class Cat { private String name; private int age; private int weight; public Cat (String name, int age, int weight) { this . name = name; this . age = age; this . weight = weight; } public Cat () { } public void sayMeow () { System. out. println ("Мяу!" ) ; } public String getName () { return name; } public void setName (String name) { this . name = name; } public int getAge () { return age; } public void setAge (int age) { this . age = age; } public int getWeight () { return weight; } public void setWeight (int weight) { this . weight = weight; } } Собственно, ограничение доступа к полям и реализация геттеров-сеттеров - самый распространенный пример использования private в реальной работе. То есть реализация инкапсуляции в программе - главное предназначение этого модификатора. Это касается не только полей, кстати. Представь, что в твоей программе существует метод, который реализует какую-то ОЧЕНЬ сложную функциональность. Что бы придумать такого для примера… Скажем, твой метод readDataFromCollider() принимает на вход адрес с данными, считывает данные из Большого Адронного Коллайдера в байтовом формате, преобразует эти данные в текст, записывает в файл и распечатывает его. Даже описание метода выглядит жутковато, что уж говорить про код:) Чтобы повысить читаемость кода, было бы хорошо не писать сложную логику метода в одном месте, а наоборот - разбить функциональность на отдельные методы. Например, метод readByteData() отвечает за считывание данных, convertBytesToSymbols() конвертирует считанные с коллайдера данные в текст, saveToFile() сохраняет полученный текст в файл, а printColliderData() - распечатывает наш файл с данными. Метод readDataFromCollider() в итоге стал бы намного проще: public class ColliderUtil { public void readDataFromCollider (Path pathToData) { byte colliderData = readByteData (pathToData) ; String textData = convertBytesToSymbols (colliderData) ; File fileWithData = saveToFile (textData) ; printColliderData (fileWithData) ; } public byte readByteData (Path pathToData) { // считывает данные в байтах } public String convertBytesToSymbols (byte colliderDataInBytes) { } public File saveToFile (String colliderData) { } public void printColliderData (File fileWithColliderData) { // печатает данные из файла } } Однако, как ты помнишь из лекции про интерфейсы, пользователь получает доступ только к конечному интерфейсу. А наши 4 метода не являются его частью. Они вспомогательные : мы создали их, чтобы улучшить читаемость кода и не засовывать четыре разные задачи в один метод. Давать доступ пользователю к этим методам не нужно. Если у пользователя при работе с коллайдером появится доступ к методу convertBytesToSymbols() , он скорее всего просто не поймет, что это за метод и зачем нужен. Какие байты конвертируются? Откуда они взялись? Зачем их конвертировать в текст? Логика, которая выполняется в этом методе, не является частью интерфейса для пользователя. Только метод readDataFromCollider() - часть интерфейса. Что же делать с этими четырьмя «внутренними» методами? Правильно! Ограничить доступ к ним модификатором private . Так они смогут спокойно выполнять свою работу внутри класса и не вводить в заблуждение пользователя, которому логика каждого из них по отдельности не нужна. public class ColliderUtil { public void readDataFromCollider (Path pathToData) { byte colliderData = readByteData (pathToData) ; String textData = convertBytesToSymbols (colliderData) ; File fileWithData = saveToFile (textData) ; printColliderData (fileWithData) ; } private byte readByteData (Path pathToData) { // считывает данные в байтах } private String convertBytesToSymbols (byte colliderDataInBytes) { // конвертирует байты в символы } private File saveToFile (String colliderData) { // сохраняет считанные данные в файл } private void printColliderData (File fileWithColliderData) { // печатает данные из файла } }

Модификатор protected

Следующий по строгости модификатор доступа - protected .
Поля и методы, обозначенные модификатором доступа protected , будут видны:
  • в пределах всех классов, находящихся в том же пакете, что и наш;
  • в пределах всех классов-наследников нашего класса.
Сходу трудно представить, когда это может понадобиться. Не удивляйся: случаев применения protected гораздо меньше, чем private , и они специфические. Представь, что у нас есть абстрактный класс AbstractSecretAgent , обозначающий секретного агента какой-то спецслужбы, а также пакет top_secret , в котором лежит этот класс и его наследники. От него наследуются конкретные классы - FBISecretAgent , MI6SecretAgent , MossadSecretAgent и т.п. Внутри абстрактного класса мы хотим реализовать счетчик агентов. При создании где-то в программе нового объекта-агента он будет увеличиваться. package top_secret; public abstract class AbstractSecretAgent { public static int agentCount = 0 ; } Но агенты-то у нас секретные! А значит, об их числе должны знать только они и никто другой. Мы легко можем добавить модификатор protected к полю agentCount , и тогда получить его значение смогут либо объекты других классов секретных агентов, либо те классы, которые расположены в нашем «секретном» пакете top_secret . public abstract class AbstractSecretAgent { protected static int agentCount = 0 ; } Вот для таких специфических задач и нужен модификатор protected:)

Модификатор package visible

Дальше у нас по списку идет модификатор default или, как его еще называют, package visible . Он не обозначается ключевым словом, поскольку установлен в Java по умолчанию для всех полей и методов. Если написать в твоем коде - int x = 10 … у переменной x будет этот самый package visible доступ. Запомнить, что он делает, легко. По сути, default = protected -наследование:) Случаи его применения ограничены, как и у модификатора protected . Чаще всего default -доступ используется в пакете, где есть какие-то классы-утилиты, не реализующие функциональность всех остальных классов в этом пакете. Приведем пример. Представь, что у нас есть пакет «services ». Внутри него лежат различные классы, которые работают с базой данных. Например, есть класс UserService , считывающий данные пользователей из БД, класс CarService , считывающий из этой же БД данные об автомобилях, и другие классы, каждый из которых работает со своим типом объектов и читает данные о них из базы. package services; public class UserService { } package services; public class CarService { } Однако легко может случиться ситуация, когда данные в базе данных лежат в одном формате, а нам они нужны в другом. Представь, что дата рождения пользователя в БД хранится в формате TIMESTAMP WITH TIME ZONE... 2014 - 04 - 04 20 : 32 : 59.390583 + 02 ...нам вместо этого нужен самый простой объект - java.util.Date . Для этой цели можем создать внутри пакета services специальный класс Mapper . Он будет отвечать за конвертацию данных из базы в привычные нам Java-объекты. Простой вспомогательный класс. Обычно мы создаем все классы как public class ClassName , но это не обязательно. Мы можем объявить наш вспомогательный класс просто как class Mapper . В таком случае он все равно делает свою работу, но не виден никому за пределами пакета services ! package services; class Mapper { } package services; public class CarService { Mapper mapper; } А это, по сути, правильная логика: зачем кому-то за пределами пакета видеть вспомогательный класс, работающий только с классами этого же пакета?

Модификатор public

И последний по списку, но не по значимости - модификатор public ! С ним ты познакомился в первый день учебы на JavaRush, впервые в жизни запустив public static void main(String args) .
Теперь, когда ты изучил лекции об интерфейсах, для тебя очевидно его предназначение:) Ведь public создан для того, чтобы отдавать что-то пользователям. Например, интерфейс твоей программы. Допустим, ты написал программу-переводчик, и она умеет переводить русский текст в английский. Ты создал метод translate(String textInRussian) , внутри которого реализована необходимая логика. Этот метод ты отметил словом public , и теперь он станет частью интерфейса: public class Translator { public String translate (String textInRussian) { // переводит текст с русского на английский } } Можно связать вызов этого метода с кнопкой «перевести» на экране программы - и все! Кто угодно может этим пользоваться. Части кода, помеченные модификатором public , предназначаются для конечного пользователя. Если привести пример из жизни, private - это все процессы, происходящие внутри телевизора, когда он работает, а public - это кнопки на пульте телевизора, с помощью которых пользователь может им управлять. При этом ему не нужно знать как устроен телевизор и за счет чего он работает. Пульт - это набор public -методов: on() , off() , nextChannel() , previousChannel() , increaseVolume() , decreaseVolume() и т.д.

Класс Modifier
Класс Modifier кодирует все модификаторы,
используемые в объявлениях типа, в виде
констант:
ABSTRACT, FINAL, INTERFACE, NATIVE,
PRIVATE, PROTECTED, PUBLIC, STATIC,
STRICT, SYBCHRONIZED, TRANSIDENT,
VOLATILE.
Каждой из констант отвечает метод запрос вида
isMod(int modifier) (тут Mod одно из выше
приведенных имен, например, isPublic),
который возвращает true, если модификатор
mod присутствует в объявлении типа.

Рассмотрим пример. Пусть имеется
объявление поля
public static final int s=10;
тогда значение возвращаемое методом
getModifiers соответствующего объекта
класса Field будет иметь вид
Modifier.PUBLIC | Modifier.STATIC |
Modifier.FINAL
Модификатор strictfp представляется
константой STRICT.
Методы- запросы можно использовать в
следующей форме

Modifier.isPrivate(field.getModifiers());
это эквивалентно следующему условию
(field.getModifiers()&Modifier.PRIVATE)!=0
Класс Field
В составе класса Field реализованы методы,
позволяющие запрашивать информацию о
типе поля, а также считывать и задавать его
значение.
Рассмотрим некоторые методы класса Field
1. getType() – возвращает объект класса
Class, отвечающий типу текущего поля.
Например, для поля типа int, получим
int.class.

2. Методы set и get – позволяют считывать
текущее значение поля, а также задавать новое.
Рассмотрим пример:
public static void printField(Object o,
String name) throws
NoSuchFieldException,
IllegalAccessException{
Field field = o.getClass().getField(name);
Short value = (Short) field.get(o);
System.out.println(value);
}
Т.е. метод get возвращает значение, на которое
ссылается соответствующее поле или объект
класса –оболочки.
Пример использования метода set имеет вид:

public static void setField(Object o, String name,
short nv) throws
NoSuchFieldException,
IllegalAccessException{
Field field = o.getClass().getField(name) ;
field.set(o,new Short(nv));
}
Для сохранения nv в поле данного объекта
необходимо использовать классы оболочки.
Существуют также методы имеющие вид
getPrimitiveType (например, getInt) и
setPrimitiveType. Эти методы можно
использовать для изменения полей в классе,
имеющих примитивный тип. Например,
field.setShort(o,nv);

Класс Method
Средства класса Method - позволяют получать
полную информацию, касающуюся
объявлений методов определенного класса,
и при необходимости вызывать эти методы в
контексте заданных объектов.
Рассмотрим методы класса Method.
1. public Class getReturnType() - возвращает
объект Class, соответствующий типу
значения, возвращаемого текущим методом.
Если вместо типа возвращаемого значения в
объявлении метода указано служебное
слово void, рассматриваемый метод вернет
объект void.class.

2. public Class getParameterTypes() - возвращает

параметров, которые заданы в объявлении
текущего метода. Объекты заносятся в массив в
том порядке, в каком параметры перечислены в
объявлении метода. Если метод не имеет
параметров, возвращается пустой массив.
3. public Class getExceptionTypes() - возвращает
массив объектов Class, соответствующих типам
исключений, которые заданы в предложении
throws объявления текущего метода. Объекты
заносятся в массив в том порядке, в каком
наименования типов исключений перечислены в
объявлении метода.

4. public Object invoke(Object onThis, Object args)
throws IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
Вызывает метод, определяемый текущим объектом
Method, в контексте объекта onThis с заданием
значений аргументов, передаваемых массивом args.
Для нестатических методов выбор реализации
осуществляется на основании фактического типа
объекта, определяемого параметром onThis. Для
статических методов onThis не принимается во
внимание и может быть равен null.
Длина массива args должна совпадать с числом
параметров в объявлении метода, а типы объектовэлементов массива должны допускать присваивание
соответствующим типам параметров метода - в
противном случае будет выброшено исключение
IIlegalArgumentException.

10.

Если в составе объекта, определяемого
параметром onThis, нет типа, членом
которого является текущий метод,
выбрасывается исключение
IllegalArgumentException.
Если значение onThis равно null и метод не
статический, генерируется исключение типа
NullPointerException.
Если выполнение вызываемого метода
завершается аварийно, выбрасывается
исключение типа InvocationTargetException.

11.

Рассмотрим пример. Вызовем средствами
рефлексии метод return str.indexOf(".", 8)
тогда имеем
try {
Сlass strClass = str.getClass();
Method indexM = strClass.getMethod("indexOf",
new Class { string.class, int.class });
Object result = indexM.invoke(str, new object {
".", new lnteger(8)});
return ((Integer) result).intValue();
}
catch (NoSuchMethodException e) { …….. }
catch (invocationTargetException e) {…….. }
catch (illegalAccessException e) {……}

12.

Класс Constructor
Для создания новых экземпляров (объектов)
типа может быть использован метод
newlnstance объекта Class,
соответствующего этому типу.
Метод вызывает конструктор без аргументов,
принадлежащий типу, и возвращает ссылку
на вновь созданный объект класса Object,
который должен быть явно преобразован к
требуемому типу.
Рассмотрим пример.

13.

static double testData = { 0.3,1.3e-2, 7.9, 3.17 };

try {
for(int arg = 0; arg < args.length; arg++){
String name = args;
Class classFor = Class.forName(name);
SortDouble sorter =
(SortDouble)classFor.newInstance();
SortMetrics metrics = sorter.sort(testData);
System.out.println(name + ": " + metrics);
for(int i =0; i < testData.length; i++)
System.out.println(“ " + testData[i]); } }
catch(Exception e) { System.err.println(e); } }

14.

Метод newlnstance при некорректном
применении способен выбрасывать большое
число объектов исключений различных
типов.
InstantiationException-если класс, объект
которого должен быть создан, не обладает
конструктором без аргументов, либо
определен как абстрактный, либо в
действительности является интерфейсом,
либо выполнение процедуры создания
объекта прерывается по каким-либо иным
причинам.
IllegalAccessException - если класс либо его
конструктор без аргументов недоступны.

15.

SecurityException - если действующая политика
безопасности запрещает создание новых объектов
ExceptionInInitializerError –выбрасывается при
инициализации класса.
В классе Constructor определены и другие методы.
public Сlass getParameterTypes()

соответствующих типам параметров, которые
заданы в объявлении текущего конструктора.
public Class getExceptionTypes()
Возвращает массив объектов Class,
соответствующих типам исключений, которые
заданы в предложении throws объявления
текущего конструктора.

16.

public Object newlnstance(Object args)
throws InstantiationException,
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException
Использует конструктор, представляемый текущим
объектом Constructor, для создания и инициализации
нового экземпляра класса, в котором конструктор
объявлен, с передачей заданных аргументов.
Возвращает ссылку на вновь созданный и
инициализированный объект. Длина массива args
должна совпадать с числом параметров в
объявлении конструктора, а типы объектовэлементов массива должны допускать присваивание
соответствующим типам параметров конструктора -
в противном случае будет выброшено исключение
IllegalArgumentException.

17.

Рассмотрим пример:
class Myclass {
private int a;
public Myclass(int k){a=k;}
public int func(int a,int b){return a+b;}
}
public class Main{
public static void main(String args){
try{
String name="Myclass";
Class mycl=Class.forName(name);
Class d={int.class};
Constructor c=mycl.getConstructor(d);
Myclass ob=(Myclass)c.newInstance(new Object{
new Integer(10)});
System.out.println(ob.func(3,5)); }
catch(Exception e){};
}}

18.

Класс AccessibleObject
Классы Field, Constructor и Method являются
производными от класса AccessibleObject,
который дает возможность разрешать или
запрещать проверку признаков доступа уровня
языка, таких как public и private.
Класс AccessibleObject имеет методы
1. public void setAccessible(boolean flag)
Устанавливает флаг доступа к объекту в
соответствии со значением аргумента: true
означает, что объект больше не подчиняется
правилам доступа, устанавливаемым на уровне
языка (и будет всегда доступен), a false
вынуждает объект поддерживать заданный
уровень доступа.
Если полномочий по изменению флага доступа
недостаточно, выбрасывается исключение типа
SecurityException

19.

2. public static
void setAccessible(AccessibleObject array,
boolean flag)
Позволяет установить флаг доступа к
объектам, передаваемым в виде массива.
Если в процессе обработки очередного
объекта выбрасывается исключение типа
SecurityException, объекты, расположенные
в массиве ранее, сохраняют вновь заданные
значения уровня доступа, а все остальные
объекты остаются в прежнем состоянии.
3. public boolean isAccessible()
Возвращает текущее значение флага доступа
к объекту

20.

Класс Array
Класс Array используется для создания массива
средствами рефлексии.
Для создания массивов используются две формы метода
newInstance.
public Object newlnstance(Class compType, int length)
Возвращает ссылку на новый массив типа compType
заданной длины length.
public Object newInstance(Class compType, int dim)
Возвращает ссылку на новый многомерный массив типа
compType, размерности которого заданы значениями
элементов массива-параметра dim.
Если массив dim пуст или обладает длиной, превышающей
допустимое число размерностей (обычно 255),

llegalArgumentException.

21.

Рассмотрим примеры.
Пример1. Сформируем массив типа byte
byte ba = (byte)
Array.newlnstance(byte.class,13);
Это равнозначно
byte ba = new byte;
Пример2.
int dims = {4, 4};
double matrix =(double)
Array.newlnstance(double.class, dims);
Это равнозначно
double matrix = new double;

22.

Класс Array обладает методами get и set.
Пусть задан массив ха значений типа int; тогда
выражению xa[i] будет соответствовать:
Integer n=Array.get(xa, i)
Присвоить значение элементу массива можно так:
xa[i] = 23; - это то же самое, что
Array.set(xa, i, new Integer(23));
Класс Package
Вызов метода getPackage класса Class позволяет
получить объект класса Package, содержащий
описание пакета, в составе которого определен
класс (сам класс Package размещен в пакете
java.lang).
Метод getName() объекта Package возвращает
полное имя текущего пакета.

23.

Класс Proxy
Класс Proxy позволяет динамически создавать
классы, реализующие один или несколько
интерфейсов.
Предположим, что имеется класс A,
реализующий некоторые интерфейсы.
Java-машина во время исполнения может
сгенерировать прокси-класс для данного
класса A, т.е. такой класс, который
реализует все интерфейсы класса A, но
заменяет вызов всех методов этих
интерфейсов на вызов метода invoke,
интерфейса InvocationHandler,для
которого можно определять свои
реализации.

24.

Создается прокси-класс с помощью вызова метода
Proxy.getProxyClass, который принимает ClassLoader и
массив интерфейсов (interfaces), а возвращает объект
класса java.lang.Class, который загружен с помощью
переданного ClassLoader и реализует переданный массив
интерфейсов.
На передаваемые параметры есть ряд ограничений:
1. Все объекты в массиве interfaces должны быть
интерфейсами. Они не могут быть классами или
примитивами.
2. В массиве interfaces не может быть двух одинаковых
объектов.
3. Все интерфейсы в массиве interfaces должны быть
загружены тем ClassLoader, который передается в метод
getProxyClass.
4. Все не публичные интерфейсы должны быть определены
в одном и том же пакете, иначе генерируемый прокси-класс
не сможет их все реализовать.

25.

5. Ни в каких двух интерфейсах не может быть
метода с одинаковым названием и
сигнатурой параметров, но с разными
типами возвращаемого значения.
6. Длина массива interfaces ограничена
65535-ю интерфейсами. Никакой Java-класс
не может реализовывать более 65535
интерфейсов.

26.

Свойства динамического прокси-класса
1. Прокси-класс является публичным, снабжен
модификатором final и не является абстрактным.
2. Имя прокси-класса по-умолчанию не
определено, однако начинается на Proxy. Все
пространство имен, начинающихся на Proxy
зарезервировано для прокси-классов
последних версиях Java это не обязательно).
3. Прокси-класс наследуется от
java.lang.reflect.Proxy.
4. Прокси-класс реализует все интерфейсы,
переданные при создании, в порядке передачи.

27.

5. Если прокси-класс реализует непубличный
интерфейс, то он будет сгенерирован в том пакете,
в котором определен этот самый непубличный
интерфейс. В общем случае пакет, в котором
будет сгенерирован прокси-класс неопределен.
6. Метод Proxy.isProxyClass возвращает true для
классов, созданных с помощью
Proxy.getProxyClass и для классов объектов,
созданных с помощью Proxy.newProxyInstance и
false в противном случае.
Данный метод используется подсистемой
безопасности Java и нужно понимать, что для
класса, просто унаследованного от
java.lang.reflect.Proxy он вернет false.

28.

Свойства созданного экземпляра прокси-класса следующие:
1. Объект прокси-класса приводим ко всем интерфейсам,
переданным в массиве interfaces. Если IDemo - один из
переданных интерфейсов, то операция proxy instanceof
IDemo всегда вернет true, а операция (IDemo) proxy
завершится корректно.
2. Статический метод Proxy.getInvocationHandler
возвращает обработчик вызовов, переданный при создании
экземпляра прокси-класса. Если переданный в данный
метод объект не является экземпляром прокси-класса, то
будет выброшено IllegalArgumentException исключение.
3. Класс-обработчик вызовов реализует интерфейс
InvocationHandler, в котором определен метод invoke,
имеющий следующую сигнатуру:
public Object invoke(Object proxy, Method method,
Object args) throws Throwable

29.

Рассмотрим пример:
package javaapplication3;
interface Account {
double getBalance();
void changeBalance(int sum);
void percents(double per);}
class MyAccount implements Account{
private double balance;
public MyAccount(){ balance=0.0; }
public double getBalance(){ return balance; }
public void changeBalance(int sum){
balance+=sum;}
public void percents(double per){
balance+=balance*per/100; }; }

30.

class MyAccountProxy implements
InvocationHandler{
private Account ac;
public MyAccountProxy(Account acc){ ac=acc; }
public static Account newInstance(Account da){
return (Account)Proxy.newProxyInstance(
da.getClass().getClassLoader(),
da.getClass().getInterfaces(),
new MyAccountProxy(da));
}

31.

public Object invoke(Object proxy,
Method method, Object args)
throws Throwable{
if(method.getName()=="percents"){
double d=((Double)args).doubleValue();
if (d<0) d=0;
if(d>30) d=30;
args=new Double(d);

else{
return method.invoke(ac, args); }
}
}

32.

public class Main{
public static void main(String args){
MyAccount ma=new MyAccount();
Account
a=(Account)MyAccountProxy.newInstance(ma);
a.changeBalance(150);

a.percents(20);
System.out.println(a.getBalance());
a.percents(35);
System.out.println(a.getBalance());} }

33.

Загрузка классов
Исполняющая система загружает классы по мере
возникновения необходимости в них.
Функциональные особенности процедур загрузки
классов существенным образом зависят от
реализации виртуальных машин Java, но в
большинстве случаев для отыскания классов,
адресуемых приложением, но не загруженных
исполняющей системой, применяется механизм
просмотра пути поиска классов.
Чтобы создать приложение, которое в состоянии
загружать классы способами, отличными от
предусмотренных по умолчанию, следует
воспользоваться объектом класса ClassLoader,
способным получить байт-код реализации нужного
класса и загрузить его в среду исполняющей
системы.

34.

Класс ClassLoader является абстрактным классом.
Для создания собственного загрузчика классов,
необходимо создать класс – наследник от
ClassLoader и переопределить метод
protected Class findClass(String name) throws
ClassNotFoundException
Который находит байт-код класса с заданным
именем name и загружает данные в среду
виртуальной машины, возвращая объект Class,
представляющий найденный класс.
Объект-загрузчик способен делегировать
полномочия по загрузке классов "родительскому"
загрузчику классов (parent class loader).
"Родительский" загрузчик классов может быть
задан в качестве аргумента конструктора класса
ClassLoader.

35.

protected ClassLoader()
Создает объект ClassLoader, неявно
используя в качестве "родительского"
загрузчика классов системный загрузчик
(который может быть получен посредством
вызова метода getSystemClassLoader).
protected ClassLoader(ClassLoader parent)
Создает объект ClassLoader, используя
заданный "родительский" загрузчик классов.
Основным в составе класса ClassLoader
является метод loadClass

36.

public Сlass loadClass(String name) throws
ClassNotFoundException
возвращает объект Class для класса с заданным
именем и при необходимости загружает этот
класс. Если класс не может быть загружен,
выбрасывается исключение типа
ClassNotFoundException.
Схема загрузки классов, предлагаемая методом
loadClass по умолчанию и обычно не
переопределяемая, выглядит так:
1. проверить посредством вызова метода
findLoadedClass класса ClassLoader, не
загружался ли заданный класс раньше; в составе
ClassLoader предусмотрена таблица объектов
Class для всех классов, загруженных средствами
текущего загрузчика классов; если класс был
загружен прежде, метод findLoadedClass
возвратит ссылку на существующий объект Class;

37.

2. если класс не загружался, вызывается
loadClass "родительского" загрузчика
классов; если текущий загрузчик не
обладает "родителем", используется
системный загрузчик классов;
3. если класс все еще не загружен,
вызывается метод findClass, выполняющий
поиск и загрузку класса.
Таким образом, необходимо реализовать
собственные версии следующих методов
ClassLoader:

38.

protected synchronized Class
loadClass(String name,boolean resolve)

protected Class findClass(String name)
throws ClassNotFoundException
protected java.net.URL findResource(String name)
protected java.util.Enumeration
findResources(String name) throws IOException
(Абстрактный класс ClassLoader представляет
только реализацию метода loadClass, основанную
на protected-методах – findLoadedClass и findClass).

39.

Рассмотрим пример.
class PlayerLoader extends ClassLoader {
public Class findClass(String name) throws
ClassNotFoundException {
try {
byte buf = bytesForClass(name);
return defineClass(name, buf, 0, buf.length);
}
catch (IOException e) {
throw new ClassNotFoundException(e.toString());
}
}
// ... Объявления метода bytesForClass и других
методов
}

40.

Метод findClass обычно выполняет две
функции.
Во-первых, он должен обнаружить байт-код
заданного класса и сохранить его в массиве
типа byte - эта обязанность в примере
возложена на метод bytesForСlass.
Во-вторых, он использует прикладной метод
defineСlass, чтобы выполнить фактическую
загрузку класса, определяемого байт-кодом.
Метод defineСlass имеет вид

41.

protected final Class defineClass(String name,
byte data, int offset, int length) throws
ClassFormatError
Возвращает объект Class для класса с заданным именем
name; бинарное представление класса передается в
виде массива data.
Для загрузки класса используются только байты,
содержащиеся в элементах массива data с индексами
от offset до offset+length. Если байты из указанного
промежутка не удовлетворяют требуемому формату
описания класса, выбрасывается объект исключения
типа ClassFormatError.
Метод ответствен за сохранение ссылки на объект
Class для загруженного класса в таблице загруженных
классов, просматриваемой методом findLoadedClass.

42.

Рассмотрим метод bytesForClass.
protected byte bytesForClass(String name) throws
lOException, ClassNotFoundException{
FileInputStream in = null;
try {


if (length == 0) throw new ClassNotFoundException(name);
byte buf = new byte;

return buf;
}
finally {
if (in!=null) in.close();
}
}

43.

Таким образом полный код имеет вид:
import java.lang.reflect.*;
import java.io.*;
class MyClassLoader extends ClassLoader{
public Class findClass(String name) throws
ClassNotFoundException {
byte buf=ReadFromBuffer(name);
if(name.equals("MyInterface1")){

} else if(buf==null) {
return findSystemClass(name);
} else {
return defineClass(name,buf,0,buf.length);
}
}

44.

protected byte ReadFromBuffer(String name) throws
ClassNotFoundException {
FileInputStream in = null;
try {
in = new FileInputStream(name + ".class");
int length = in.available(); // число доступных байтов
if (length == 0) throw
new ClassNotFoundException(name);
byte buf = new byte;
in.read(buf); // Считывание байтов
return buf;
}
catch(FileNotFoundException e){ return null;}
catch(IOException e){ return null;}
finally{
try{ if (in!=null) in.close(); }
catch(IOException e){ }
}
}

45.

protected synchronized Class
loadClass(String name,boolean resolve) throws
ClassNotFoundException{
Class result= findClass(name);
if (resolve) resolveClass(result);
return result;
}
}

46.

public class Main1 {
public static void main(String args) {
try{
String name="Myclass";
ClassLoader ld=new MyClassLoader();
Class cl=Class.forName(name, true, ld);
Constructor s=cl.getConstructor(int.class);
MyInterface1
ob=(MyInterface1)s.newInstance(
new Integer(8));
System.out.println(ob.func(3,5));
}catch(Exception e){ };
}
}

47.

public interface MyInterface1{
public int func(int a,int b);
}
public class Myclass implements MyInterface1 {
private int a;
public Myclass(int k) { a=k; }
public int func(int a,int b){ return a+b; }