Java модификатори. Модификатори за достъп

Ще говорим за модификатори: какво представляват модификатори, обхвати, модификатори за класове, полета, методи. Не мисля, че ще е скучно.

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

За да се укаже видимостта на даден клас на неговите методи и полета, има 4 модификатора за достъп:

  • частенчленовете на класа са достъпни само в рамките на класа;
  • частен пакет или по подразбиране (по подразбиране)членовете на класа са видими вътре в пакета;
  • защитеничленовете на класа са налични в пакета и в производни класове;
  • публиченчленовете на класа са достъпни за всички.

Ако си спомняте, в края, когато вече бяхме импортирали класа Cat, все още имахме грешка при компилиране.

Работата е там, че не сме регистрирали никакви модификатори за достъп до нашите полета и методи и те имат свойство по подразбиране (членовете на класа са видими вътре в пакета). За да коригираме грешката при компилиране на нашия код и най-накрая да го изпълним, трябва да направим нашия конструктор и методи публични. Тогава те могат да бъдат извикани от други пакети.

Може да започнете да се чудите: за какво е всичко това? Защо не направите кода видим от всеки пакет или клас, но трябва да ограничите достъпа? Тези въпроси ще изчезнат сами, когато дойде време за писане на сложни и тромави проекти. Сега, когато пишем приложения, чиято функционалност е ограничена до един или два класа, тогава изглежда няма смисъл да ограничаваме нищо.

Представете си, че имате клас, който показва обект на някакъв продукт. Например кола. Колата може да има цена. Вие сте създали ценовото поле и много други полета, куп методи, които отговарят за функционалността. Изглежда всичко е наред. Вашият класен автомобил е част от огромен проект и всички са доволни. Но да кажем, че някой случайно или нарочно е създал екземпляр от класа на автомобила и е поставил отрицателна цена. Може ли един продукт да има отрицателна цена? Това е много примитивен пример и е малко вероятно да се случи в Истински животно мисля, че идеята е ясна. Понякога трябва да дадете достъп не директно, а чрез определени методи. Възможно е кодът да отговаря за функционалността на друг код и не искате някой да променя и редактира част от вашия. За това има ограничение на достъпа.

Модификаторът за достъп за конструктори, методи и полета може да бъде всеки. Един клас може да бъде само публичен или по подразбиране и само един публичен клас може да бъде в един файл.

Стига за модификаторите на достъп засега. В статията "Обектно-ориентирано програмиране" ще говорим за тях по-подробно, но сега нека поговорим за други модификатори, от които, между другото, има много.

Сега модификаторът е следващият статичен. Може да се използва преди метод, поле или дори клас, когато искаме да декларираме вложен клас. В Java можете да пишете класове вътре в други класове и ако модификаторът е преди класа вътре в статичния клас, тогава такъв клас се нарича вложен, ако е друг модификатор или по подразбиране, тогава такъв клас се нарича вътрешен. Ще има отделна статия за вложените и вътрешните класове, тъй като там всичко не е толкова просто.

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

    Модификатори на публичен клас (

    static int anotherStaticField = 5;

    public static void myStaticMethod() (

    someField = "Моето поле";

    //nonStaticField = ""; грешка при компилиране

    //не може да използва нестатични полета

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

    public void myNonStaticMethod() (

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

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

    //основният метод също има статичен модификатор

    нови Модификатори() .myNonStaticMethod() ;

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

    //чрез classname.method

Друга важна бележка за статичните модификатори е, че статичните полета се инициализират по време на зареждане на класа. Често в различни видове Java тестове можете да намерите код като този:

Въпрос: какво ще бъде изведено на конзолата? Трябва да се помни, че статичният блок ще се покаже първи във всеки случай. Следва блокът по подразбиране. След това погледнете екрана на конзолата:

Следващият модификатор, който ще разгледаме, е финал.

Мисля, че думата финал говори сама за себе си. С прилагането на крайния модификатор вие казвате, че полетата не могат да се променят, методите се отменят и класовете не могат да се наследяват (ще има отделна статия за наследяването). Този модификатор се прилага само за класове, методи и променливи (също локални променливи).

С последния модификатор на методи и класове ще говорим в статията за ООП.

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

Модификатор синхронизиранипоказва, че методът може да се използва само от една нишка в даден момент. Въпреки че това може да не ви каже нищо, полезността на този модификатор ще стане очевидна, докато изследваме многонишковостта.

Модификатор преходен- казва, че по време на сериализирането на обект определено поле трябва да се игнорира. По правило такива полета съхраняват междинни стойности.

Модификатор летлив- използва се за многопоточност. Когато поле с модификатора volatile ще бъде използвано и модифицирано от множество нишки, този модификатор гарантира, че полето ще бъде модифицирано едно по едно и няма да има объркване с него.

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

Модификатор strictfp- Гарантира изпълнението на операции с числа от тип float и double (с плаваща запетая) съгласно стандарта IEEE 754. Или казано по-просто, гарантира, че в рамките на метода резултатите от изчисленията ще бъдат еднакви на всички платформи.

Все още не съм говорил за модификатора абстрактно. Ще ви разкажа накратко за това, тъй като без да познавам основите на обектно-ориентираното програмиране, не виждам смисъл да говоря за това.

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

Ще говорим повече за абстрактния модификатор в статията за ООП.

Това завършва статията за модификаторите. За тях не е казано много. Но това се дължи на факта, че все още нямаме концепциите за ООП. В няколко статии ще допълним знанията за модификаторите и ще попълним празнините.

Което добавяте по време на инициализацията, за да промените стойностите. Езикът Java има широка гама от модификатори, основните от които са:

  • модификатори за достъп;
  • модификатори на клас, метод, променлива и нишка, които не се използват за достъп.

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

публичен клас className ( // ... ) private boolean myFlag; статични крайни двойни седмици = 9,5; защитен статичен финал int BOXWIDTH = 42; public static void main(String arguments) ( // тяло на метода )

Модификатори за достъп

Java предоставя редица модификатори за достъп за задаване на нива на достъп за класове, променливи, методи и конструктори. Има четири достъпа:

  • Вижда се в пакета (по подразбиране и не се изисква модификатор).
  • Видим само за класа (личен).
  • Видим за всички (обществено).
  • Видим за пакета и всички подкласове (защитен).

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

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

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

Пример

Променливите и методите могат да бъдат декларирани в Java без никакви модификатори, както е показано в следния пример:

Версия на низ = "1.5.1"; boolean processOrder() (връщане true;)

модификатор за частен достъп

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

Модификаторът за частен достъп е най-рестриктивното ниво на достъп. Класът и интерфейсите не могат да бъдат лични.

Променливите, декларирани като частни, могат да бъдат достъпни извън класа, ако публичните методи, които ги получават, присъстват в класа (вижте примера и обяснението по-долу).

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

Пример

Следният клас използва частен контрол на достъпа:

Публичен клас Logger ( частен формат на низ; публичен низ getFormat() ( връщане на този.формат; ) публичен void setFormat(формат на низ) ( this.format = формат; ) )

Ето променливата форматклас дървосекаче private, така че няма начин други класове да получат и зададат стойността му директно.

Така че, за да направим тази променлива достъпна за всички, сме дефинирали два публични метода: getFormat(), който връща стойност формат, И setFormat (низ), който определя неговата стойност.

модификатор за обществен достъп

обществен модификатор- клас, метод, конструктор, интерфейс и др. деклариран като public може да бъде достъпен от всеки друг клас. Следователно, полета, методи, блокове, декларирани в публичния клас, могат да бъдат достъпни от всеки клас, принадлежащ към "вселената" на Java.

Въпреки това, ако се опитваме да получим достъп до публичен клас в друг пакет, тогава публичният клас трябва да бъде импортиран.

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

Пример

Следната функция използва публичен контрол на достъпа:

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

Метод основен ()трябва да е публичен. В противен случай не може да бъде извикан от java интерпретатора, за да изпълни класа.

модификатор на защитен достъп

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

Модификаторът за защитен достъп в Java не може да се прилага към класове и интерфейси. Методите и полетата могат да бъдат декларирани като защитени, но методите и полетата в интерфейс не могат да бъдат декларирани като защитени.

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

Пример

Следният родителски клас използва защитен контрол на достъпа, така че дъщерният му клас заменя метода openSpeaker():

Клас AudioPlayer ( protected boolean openSpeaker(Speaker sp) ( // подробности за изпълнението ) ) клас StreamingAudioPlayer ( boolean openSpeaker(Speaker sp) ( // подробности за изпълнението ) )

Ако обаче дефинираме метод openSpeaker()като защитен, той няма да бъде достъпен от друг клас освен AudioPlayer. Ако го определим като публичен, тогава той ще стане достъпен за всички. Но нашето намерение е да изложим този метод само на подкласа, поради което използвахме защитения модификатор.

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

Следните правила в Java се прилагат за наследените методи:

  • Методите, декларирани за публични в суперклас, също трябва да бъдат публични във всички подкласове.
  • Методите, декларирани като защитени в суперклас, трябва да бъдат или защитени, или публични в подкласове; те не могат да бъдат частни.
  • Методите, декларирани като частни, не се наследяват от всички, така че за тях няма правило.

Модификаторите на клас, метод, променлива и нишка не се използват за достъп

Java предоставя редица модификатори не за достъп, а за реализиране на много други функции:

  • модификатор статиченизползвани за създаване на методи и променливи на клас;
  • модификатор финализползвани за завършване на изпълнението на класове, методи и променливи;
  • модификатор абстрактнонеобходими за създаване на абстрактни класове и методи;
  • модификатори синхронизираниИ летливсе използват в Java за нишки.

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

статичен модификатор- използва се за създаване на методи и променливи на класа.

статични променливи

Ключовата дума static се използва за създаване на променливи, които ще съществуват независимо от всички екземпляри, създадени за класа. В Java съществува само едно копие на статична променлива, независимо от броя на екземплярите на класа.

Статичните променливи са известни също като променливи на класа. В Java локалните променливи не могат да бъдат декларирани като статични.

статични методи

Ключовата дума static се използва за създаване на методи, които ще съществуват независимо от всички екземпляри, създадени за класа.

В Java статичните или статичните методи не използват никакви променливи на екземпляр на който и да е обект от клас, те са дефинирани. Статичните методи вземат всички данни от параметрите и някои от тези параметри се оценяват без препратка към променливите.

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

Пример

Статичният модификатор в Java се използва за създаване на методи и променливи на клас, както е показано в следния пример:

Публичен клас 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, никога не може да бъде присвоена за препратка към друг обект.

Данните в обекта обаче могат да бъдат променяни. Така може да се промени състоянието на обекта, но не и препратката.

С променливите в Java, финалният модификатор често се използва със static, за да направи променливата на класа константа.

Пример

public class Test( final int value = 10; // Ето примери за константни декларации: public static final int BOXWIDTH = 6; static final String TITLE = "Manager"; public void changeValue(){ value = 12; //будет получена ошибка } } !}

крайни методи

Последният метод не може да бъде заменен от нито един подклас. Както бе споменато по-рано, в Java финалният модификатор предотвратява модифициране на метод от подклас.

Основното намерение да се направи метод окончателен би било съдържанието на метода да не се променя отстрани.

Пример

Декларацията на метод, който използва крайния модификатор в декларация на клас, е показана в следния пример:

Публичен клас Test( public final void changeName()( // тяло на метода))

последен клас

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

Пример

публичен финален клас Тест ( // тяло на класа )

абстрактен модификатор

абстрактен модификатор- използва се за създаване на абстрактни класове и методи.

абстрактен клас

Абстрактният клас не може да бъде създаден. Ако един клас е обявен за абстрактен, тогава единствената му цел е да бъде разширен.

Един клас не може да бъде едновременно абстрактен и окончателен, защото последният клас не може да бъде разширен. Ако даден клас съдържа абстрактни методи, тогава той трябва да бъде обявен за абстрактен. В противен случай ще се генерира грешка при компилиране.

Един абстрактен клас може да съдържа както абстрактни методи, така и обикновени.

Пример

abstract class Caravan( private double price; private String model; private String year; public abstract void goFast(); //abstract method public abstract void changeColor(); )

абстрактен метод

Абстрактен метод е метод, деклариран с произволна реализация. Тялото на метода (имплементация) се предоставя от подкласа. Абстрактните методи никога не могат да бъдат окончателни или строги.

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

Ако клас в Java съдържа един или повече абстрактни методи, тогава класът трябва да бъде обявен за абстрактен. Не се изисква абстрактен клас да съдържа абстрактни методи.

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

Пример

публичен абстрактен клас SuperClass( abstract void m(); //abstract method ) class SubClass extends SuperClass( // implements abstract method void m()( ......... ) )

синхронизиран модификатор

синхронизиран модификатор

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

Пример

публичен синхронизиран void showDetails()( ....... )

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

Променлива на екземпляр, означена като преходен, показва виртуална машина Java (JVM), за да пропуснете определена променлива при сериализиране на обекта, който я съдържа.

Този модификатор е включен в оператора, който създава променлива от предшестващия клас или тип данни на променливата.

Пример

публичен преходен int limit = 55; // няма да се запази public int b; // ще бъдат запазени

летлив модификатор

летлив модификатор- се използват в Java за нишки.

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

Достъпът до променлива променлива синхронизира всички кеширани копирани променливи в оперативна памет. Volatile може да се прилага само към променливи на екземпляри, които са от тип object или private. Препратката към непостоянен обект може да бъде нула.

Пример

публичен клас MyRunnable внедрява Runnable( private volatile boolean active; public void run()( active = true; while (active)( // line 1 // some code here) ) public void stop()( active = false; / / line 2))

Обикновено run() се извиква в една нишка (това е първият път, когато започвате да използвате Runnable в Java), а stop() се извиква в друга нишка. Ако кешираната активна стойност се използва на ред 1, тогава цикълът не може да спре, докато не зададете active на false на ред 2.

В следващия урок ще обсъдим основните оператори, използвани в езика Java. Този раздел ще ви даде общ преглед на това как можете да ги използвате по време на разработката на приложения.

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

Методът на достъп е определен модификатор за достъп, който се добавя при декларацията. Има общо четири:

  • частен (затворен)
  • публичен (отворен)
  • защитен (защитен)
  • достъп по подразбиране, когато няма модификатор

Примери за декларации на модификатор (винаги трябва да е на първо място):

public int i; частно двойно j, k; private int createMethod(int a) (...); публичен клас Cat()

Както можете да видите, модификаторът е приложим към променлива, метод, клас.

публичен

Когато използвате ключовата дума публиченвие казвате, че декларацията на член на класа, която следва, е достъпна за всеки от всеки друг код във вашия проект.

Да предположим, че класът е деклариран като публичен, и има два метода. един частен, второ - публичен. Ще имате достъп до класа и второметод, но не и към първия, въпреки факта, че самият клас е публичен.

частен

Ключова дума частенозначава, че достъп до член на клас не се дава на никого, освен на методите на този клас. Други класове в същия пакет също нямат достъп до частни членове.

Всички помощни методи на класове трябва да бъдат декларирани като частенза да ги предотвратите случайно извикване в пакет. Същото важи и за частни полета в клас.

защитени

Ключова дума защитенисе свързва с концепцията за наследяване, при която нови членове се добавят към вече съществуващ клас (базов клас), докато оригиналната реализация остава непроменена. Можете също да промените поведението на съществуващите членове на класа. За да създадете нов клас на базата на съществуващ, използвайте ключовата дума се простира.

Когато нов пакет е създаден с помощта на наследяване от клас в друг пакет, новият клас има достъп само до публичните членове в оригиналния пакет. Понякога създателят на базов клас трябва да даде достъп до определен метод на производни класове, но да го скрие от всички останали. В тези случаи се използва ключовата дума защитени. спецификатор защитенисъщо осигурява достъп в рамките на пакета, т.е. членовете с този спецификатор са достъпни за други класове в същия пакет.

По подразбиране, ако не е приложен модификатор, членът на класа се счита за публичен в рамките на собствения си пакет, но не е достъпен за кодиране извън този пакет. Ако всички класове на вашия проект са в един и същи пакет, тогава по същество променлива без модификатор е публична ( публичен).

Помислете за измислен клас SillySensor

Публичен клас SillySensor ( private int sensorData; public SillySensor() ( sensorData = 0; ) private void calibrate(int iSeed) ( // код за калибриране) protected void seedCalibration(int iSeed) ( calibrate(iSeed); ) public int getSensorData( ) ( // Проверете сензора тук, върнете сензорните данни; ) )

Класът е деклариран като публичени налични в други класове. Класът има променлива сензорни данни, който е достъпен само в своя клас (private). Конструкторът е наличен в други класове ( публичен). Метод калибриране()работи само вътре в клас ( частен). Метод seedCalibration()наличен в своя клас или в подклас ( защитени). Метод getSensorData()налични в други класове ( публичен).

5

Видях някои дискусии в StackOverflow по тази тема, но не виждам нищо, което да ми помогне да разбера следната точка:

Идвам от C++ фон и наскоро започнах да уча Java. В C++, когато защитени, се използва само подкласът, който има достъп до члена (аналогично на поле в Java).

В C++ има и "приятелски" класове, които имат достъп до частни/сигурни класове, които дават "приятелство". Това е малко като модификатора на полето "package" в Java (модификатора на полето по подразбиране), с изключение на това, че в C++ friendship дава достъп до всички частни членове, но в Java достъпът от класове в същия пакет е специфичен за полето на класа,

Това, което не мога да разбера, ако приемем, че искам да дам достъп само до подкласове, е какво мога да направя в C++, като декларирам защитени членове в клас, който не "дава" приятелско отношение.

Но в Java не знам как да направя това, тъй като с модификатора на полето "protected" - аз също давам достъп до всички класове в пакета. Единственият начин, който намирам да направя това, е да декларирам защитено поле и да изолирам класа във вашия пакет.

От това заключавам, че групирането на класовете в един пакет трябва да става на базата на "приятелство" между класовете. Това наистина ли е водещият фактор при групиране на пакети?

Още нещо, което не разбирам, В Java, ако приемем, че имам две полета в клас A: b, c. Искам да дам на B достъп до b, но не и до, и искам да дам на C достъп до c, но не и b. и на "Свят" искам b, c да се скрие. Как мога да направя това? Предполагам, че B, C трябва да са в същия пакет като A. , но чрез деклариране на b, c с пакетмодификатор Позволявам на B, C достъп до b и c. Има ли начин в Java да направите това?

Надявам се на някакво обяснение на този въпрос

11

По-добър въпрос, ако е по-малко полезен за вас, би бил по-тесен и конкретен. Общият въпрос "всичко за поверителността в Java и C++ и как се различават" е повече от твърде широк. Може ли да попитате повече конкретен въпросза по-конкретен въпрос? - Якк 04 мар 15 2015-03-04 16:38:58

  • 4 отговора
  • Сортиране:

    Дейност

2

В C++, когато се използва защита, само подклас има достъп до елемента (аналогично на поле в Java).

Спецификаторите за достъп също са за членски функции/методи, а не само за членски променливи.

В C++ има и "приятелски" класове, които могат да имат достъп до частните/защитените членове на класа, което дава "приятелство". Това е малко подобно на модификатора на полето "пакет" на Java (модификатор на поле по подразбиране), с изключение на това, че в C++ friendship дава достъп до всички частни членове, но в Java достъпът от класове в същия пакет е специфичен за полето на класа.

Има не само приятелски класове, но и функции.

Вярно е, че достъпът до личните части на Java е подобен, но не е пълна замяна. По-добре е да се каже, че тези две функции имат подмножествопроблемите, които решават. Има проблеми, които могат да бъдат решени от приятел, но не и частен пакет, и обратното.

Това, което не можах да разбера, ако приемем, че искам да предоставя достъп само до подкласове, е какво мога да направя в C++, като декларирам потребителите като защитени в клас, който не "дава" приятелство.

Но в Java не знам как мога да го направя,

Отговор: Не можете.

тъй като с модификатора на полето "protected" - аз също давам достъп до всички класове в пакета.

Единственият начин, който намирам, е да декларирам защитено поле и да изолирам класа в неговия пакет.

Технически, да. Но това създава други проблеми. Вашият клас вече няма да има достъп до личните части на пакета от предишния си пакет. Да приемем, че вашият BaseClass е в com.example.one. Ще го преместите в com.example.two. Сега вече няма да има достъп до други частни класове на пакета на com.example.one.

Това наистина ли е водещият фактор при групиране на пакети?

Да, Java е проектирана по този начин. Можете да опитате борете се с правилата на езика, но това е загубена битка на всеки език за програмиране.

Друго нещо, което не разбирам, е в Java, ако приемем, че имам две полета в клас A: b, c. Искам да дам на B достъп до b, но не и до, и искам да дам на C достъп до c, но не и b. и в "Свят" искам b, c да се скрие. Как мога да направя това?

Не може да се направи по чист начин (чист имам предвид: без никакви хакове, които биха изисквали да проверявате стека на извикванията по време на изпълнение и да хвърляте изключения).

Ако сте загрижени за този сценарий, тъй като разработвате публичен API, нискотехнологично решение, което обикновено работи чудесно, е да създадете един или повече *.internal пакети и ясно да документирате факта, че те не трябва да се използват в клиентски код.

1

Това са доста въпроси...

Но в Java не знам как мога да направя това, тъй като по силата на използването на модификатора на "защитеното" поле - аз също давам достъп до всички класове в пакета.

Всъщност няма начин да се предостави достъп само до подкласове, а не до класове в същия пакет. Това беше дизайнерско решение, взето преди векове...

Единственият начин, който намирам да направя това, е да декларирам защитено поле и да го изолирам в моя пакет.

Това е технически правилно, въпреки че няма да има голяма полза. Пакетирането на класове е за групиране на свързани класове, където „свързани“ означава „класове, които изпълняват конкретна връзка“, т.е. те принадлежат към един и същ случай на употреба, принадлежат към едно и също архитектурно ниво, са в едни и същи обекти и т.н.

От това заключавам, че групирането на класовете в един пакет трябва да става на базата на "приятелство" между класовете. Това наистина ли е водещият фактор при групиране на пакети?

Вярвам, че вече отговорих на това в предишния параграф: опаковането е за групиране на свързани класове според някои специфични критерии.

За вашите A, B и C класове, например с атрибути:

Мисля, че B, C трябва да са в един и същ пакет като A. a декларира b, с модификатора на опаковката позволявам на B, C да имат достъп до b и c. Има ли начин в Java да се направи това?

Отговорът е не, няма прост и чист начин да направите това. Можете да постигнете това с някои хакове или по-напреднали техники, но отново, това беше част от решенията, взети от дизайнерите на езика преди много време...

0

Кратък отговор: няма начин да стане това.

Ако се притеснявате от проникване от инжектиране на клиенти на клас в пакет за получаване на неоторизиран достъп, можете да преместите чувствителния код в отделен пакет и да направите пакета запечатан в буркана, на който го доставяте: http://docs.oracle .com/javase/tutorial /deployment/jar/sealman.html

1

Неявно се предполага, че всички класове в пакет се „познават“ (защото са написани от едно и също лице/компания/организация). Така те или не получават достъп до защитени полета, или ако имат, знаят как да го направят правилно.

Предполага се, че класовете в един и същи пакет са по-свързани един с друг, отколкото родителят е с производен клас, тъй като производният клас може всъщност да е написан от някой друг. Затова решиха, че частната защита е по-скоро ограничена, отколкото сигурна.

Така че предполагам, че не е нужно да се притеснявате за това как класовете в един и същ пакет могат да имат достъп до полетата на другия. По принцип просто не използвам тази функция, освен когато пиша итератори.

Ако имате две полета, можете да ги направите вътрешни класове, така че да имат достъп до частни полета (отново, логика: ако даден клас е вътре в друг клас, той знае за семантиката на този клас) и може да предостави този достъп до своите производни класове чрез защитени методи.

Разбира се, бихте могли да измислите сложен протокол за обмен на токени, за да направите това поле достъпно само за B/C екземпляри, но това би било чудесно натоварване и друг обект все още може да използва отражение за достъп до всички частни членове, ако не го деактивирате с политики за сигурност, което обикновено не е така, но отново, политиките за сигурност в крайна сметка се решават от собственика на JVM.

Така че в крайна сметка предпочитаният начин да направите това, което казвате в Java, е или да ги поставите в един и същ пакет, или да напишете B и C като вътрешни класове на A, така че да могат директно да имат достъп до частните членове на A и да ги изложат на техните производни класове.

Публичен клас A ( публичен статичен абстрактен клас B ( protected Whatever getWhatever(A a) ( return a.b; ) protected void setWhatever(A a, Whatever value) ( ​​​​a.b = value; ) ) public static abstract class C ( protected Whatever getWhatever (A a) ( return a.c; ) protected void setWhatever(A a, Whatever value) ( ​​​​a.c = value; ) ) private Whatever b; private Whatever c; )

отново, вие винаги приемате, че класовете в един и същ пакет никога няма да направят нещо нередно.

Здравейте! В днешната лекция ще се запознаем с понятието „ модификатори за достъпи разгледайте примери за работа с тях. Въпреки че думата „запознайте се“ няма да е съвсем правилна: вече сте запознати с повечето от тях от предишни лекции. За всеки случай, нека опресним паметта на основното. Модификатори за достъпнай-често са ключови думи, които регулират нивото на достъп до различни части от вашия код. Защо "най-често"? Тъй като един от тях е зададен по подразбиране и не е маркиран ключова дума:) В Java има четири модификатора за достъп. Изброяваме ги по ред от най-строгите до най-"меките":

  • частни;
  • защитени;
  • по подразбиране (пакетът е видим);
  • публичен.
Нека да разгледаме всеки от тях, да решим кога могат да ни бъдат полезни и да дадем примери :)

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


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 ("Meow!" ) ;) ) public class Main ( public static void main (String args) ( Cat cat = new Cat () ; cat. name = " " ; кат. възраст = - 1000 ; кат. тегло = 0 ; ) ) Разгледахме го в една от статиите по-рано. Тук направихме сериозна грешка: отворихме нашите данни, в резултат на което колегите програмисти получиха достъп директно до полетата на класа и промениха стойността им. Освен това тези стойности бяха присвоени без проверки, в резултат на което в нашата програма е възможно да създадем котка на възраст -1000 години, име "" и тегло 0. За да разрешим този проблем, ние използвани гетери и сетери, а също и ограничен достъп до данни с помощта на частния модификатор. публичен клас Cat ( частно име на низ; частно int възраст; частно int тегло; public Cat (име на низ, int възраст, int тегло) ( this . name = име; this . age = възраст; this . 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; ) ) Всъщност , ограничаване на достъпа до полета и внедряване на getter-setter е най-честият случай на използване на 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) ; printColli derData ( fileWithData) ; ) публичен байт readByteData(Path pathToData) ( // чете данни в байтове) public String convertBytesToSymbols (byte colliderDataInBytes) ( ) public File saveToFile (String colliderData) ( ) public void printColliderData (File fileWithColliderData) ( // отпечатване на данни от файл) ) Но както си спомняте от лекцията за интерфейсите, потребителят получава достъп само до крайния интерфейс. И нашите 4 метода не са част от него. Те спомагателни: създадохме ги, за да подобрим четливостта на кода, а не да поставяме четири различни задачив един метод. Не е необходимо да давате на потребителя достъп до тези методи. Ако потребителят има достъп до метода convertBytesToSymbols(), докато работи с колайдера, той най-вероятно просто няма да разбере какво представлява този метод и защо е необходим. Какви байтове се преобразуват? Откъде са дошли? Защо да ги конвертирате в текст? Логиката, която се изпълнява в този метод, не е част от потребителския интерфейс.Само методът readDataFromCollider() е част от интерфейса. Какво да правим с тези четири "вътрешни" метода? вярно! Ограничете достъпа до тях с частния модификатор. Така те могат безопасно да вършат работата си вътре в класа и да не подвеждат потребителя, който не се нуждае от логиката на всеки един от тях поотделно. public class ColliderUtil ( public void readDataFromCollider (Path pathToData) ( byte colliderData = readByteData (pathToData) ; String textData = convertBytesToSymbols (colliderData) ; File fileWithData = saveToFile (textData) ; printColliderData (fileWithData) ; ) частен байт readB yteData (Path pathToData) ( // чете данни в байтове) private String convertBytesToSymbols (byte colliderDataInBytes) ( // конвертиране на байтове в знаци) private File saveToFile(String colliderData) ( // запишете прочетените данни във файл) private void printColliderData(File fileWithColliderData)( // отпечатване на данни от файл } }

защитен модификатор

Следващият най-рестриктивен модификатор за достъп е защитен.
Полетата и методите, маркирани с модификатора за защитен достъп, ще бъдат видими:
  • във всички класове, които са в същия пакет като нашия;
  • във всички класове, които наследяват от нашия клас.
Трудно е да си представим кога това може да е необходимо. Не се изненадвайте: има много по-малко употреби за protected отколкото за private и те са специфични. Представете си, че имаме абстрактен клас AbstractSecretAgent, обозначаващ таен агент на някаква специална услуга, както и пакет top_secret, който съдържа този клас и неговите наследници. От него са наследени конкретни класове - FBISecretAgent , MI6SecretAgent , MossadSecretAgent и др. Вътре в абстрактния клас искаме да внедрим брояч на агенти. Когато някъде в програмата се създаде нов обект на агент, той ще се увеличи. пакет top_secret; публичен абстрактен клас AbstractSecretAgent ( public static int agentCount = 0 ; ) Но нашите агенти са тайни! Така че само те и никой друг не трябва да знаят за броя им. Можем лесно да добавим защитения модификатор към полето agentCount и след това или обекти от други класове на таен агент, или онези класове, които се намират в нашия „таен“ пакет top_secret, могат да получат неговата стойност. публичен абстрактен клас AbstractSecretAgent ( protected static int agentCount = 0 ; ) За такива специфични задачи е необходим защитен модификатор :)

пакет видим модификатор

Следващият в списъка е модификаторът по подразбиране или, както се нарича още, пакет видим. Не е маркиран с ключова дума, защото е зададен по подразбиране в Java за всички полета и методи. Ако напишете в кода си - int x = 10 ... променливата x ще има същия този пакет видим достъп. Лесно е да запомните какво прави. Всъщност по подразбиране = защитено -наследяване :) Случаите на неговото използване са ограничени, като модификатора protected. Най-често достъпът по подразбиране се използва в пакет, където има някои помощни класове, които не изпълняват функционалността на всички други класове в този пакет. Да вземем пример. Представете си, че имаме пакет услуги". В него има различни класове, които работят с базата данни. Например, има клас UserService, който чете потребителски данни от базата данни, клас CarService, който чете данни за автомобили от същата база данни, и други класове, всеки от които работи със собствен тип обекти и чете данни за тях от базата данни . пакетни услуги; публичен клас UserService ( ) пакетни услуги; public class CarService ( ) Лесно обаче може да се случи данните в базата данни да са в един формат, но да ни трябват в друг. Представете си, че датата на раждане на потребител в базата данни се съхранява във формат TIMESTAMP WITH TIME ZONE... 2014 - 04 - 04 20 : 32 : 59.390583 + 02 ...вместо това ни трябва най-простият обект - java.util. Дата . За тази цел можем да създадем специален клас Mapper в пакета услуги. Той ще отговаря за преобразуването на данни от базата данни в познатите ни Java обекти. Прост помощен клас. Обикновено създаваме всички класове като публичен клас ClassName, но това не е задължително. Можем да декларираме нашия помощен клас просто като class Mapper. В този случай той все още си върши работата, но не се вижда от никого извън пакета услуги! пакетни услуги; клас Mapper() пакет услуги; публичен клас CarService ( Mapper mapper; ) И това по същество е правилната логика: защо някой извън пакета би виждал помощен клас, който работи само с класове в същия пакет?

обществен модификатор

И не на последно място публичният модификатор! Срещнахте го в първия си ден в JavaRush, изпълнявайки public static void main(String args) за първи път в живота си.
Сега, след като изучихте лекциите за интерфейсите, целта му е очевидна за вас :) Все пак public е създаден, за да даде нещо на потребителите. Например интерфейсът на вашата програма. Да приемем, че сте написали програма за преводач и тя може да превежда руски текст на английски. Създали сте метода translate(String textInRussian), в който е внедрена необходимата логика. Вие маркирахте този метод с думата public и сега той ще стане част от интерфейса: public class Translator ( public String translate (String textInRussian) ( // превежда текст от руски на английски) ) Можете да свържете това извикване на метод с бутона "превод" на екрана на програмата - и това е! Всеки може да го използва. Части от кода, маркирани с публичен модификатор, са предназначени за крайния потребител. За пример от живота частни са всички процеси, които протичат вътре в телевизора, когато работи, а публични са бутоните на дистанционното управление на телевизора, с които потребителят може да го управлява. В същото време той не трябва да знае как е подреден телевизорът и как работи. Конзолата е набор от публични методи: on() , off() , nextChannel() , previousChannel() , increaseVolume() , reduceVolume() и т.н.

Зареждане...
Връх