JavaRush /Java Blog /Random-TK /Java @ Bellikler. Bu näme we ony nädip ulanmaly?
SemperAnte
Dereje
Донецк

Java @ Bellikler. Bu näme we ony nädip ulanmaly?

Toparda çap edildi
Bu makala hiç haçan Annotasiýa bilen işlemedik, ýöne onuň nämedigine we näme bilen ulanylýandygyna düşünmek isleýän adamlar üçin niýetlenendir. Bu ugurda tejribäňiz bar bolsa, bu makala belli bir derejede bilimiňizi giňelder öýdemok (we aslynda beýle maksady amala aşyrmaýaryn). Mundan başga-da, makala ýaňy Java dilini öwrenip başlaýanlar üçin amatly däl. Kartanyň <> ýa-da HashMap <> nämedigine düşünmeýän bolsaňyz ýa-da synp kesgitlemesiniň içindäki statiki { girişiň manysyny bilmeseňiz ýa-da hiç haçan pikirlenmek bilen işlemedik bolsaňyz, bu makalany okamagyňyz entek ir we düşündirişleriň nämedigine düşünmäge synanyşyň. Bu guralyň özi täze başlanlar tarapyndan ulanmak üçin döredilmedi, sebäbi synplaryň we obýektleriň özara täsirine düýbünden düşünmeli däl (meniň pikirimçe) (bu ýazgynyň zerurlygyny görkezen teswirleriň kömegi bilen). Java @ Bellikler.  Bu näme we ony nädip ulanmaly?  - 1Geliň, başlalyň. Java-daky bellikler, funksiýa / synp / paket üçin meta-maglumaty beýan edýän koddaky bellikleriň bir görnüşidir. Mysal üçin, ene-atalar synpynyň usulyny ýok etjekdigimizi görkezýän meşhur @Override Annotasiýa. Hawa, bir tarapdan, onsuz mümkin, ýöne ene-atalarda bu usul ýok bolsa, kody biderek ýazmagymyz ähtimal, sebäbi Bu aýratyn usul hiç haçan atlandyrylyp bilinmez, ýöne @Override Annotasiýa bilen düzüji bize: "Ene-atalarda beýle usuly tapmadym ... bu ýerde bir zat hapa". Şeýle-de bolsa, bellikler diňe “ygtybarlylyk üçin” manysyny däl-de, eýsem soňra ulanyljak käbir maglumatlary saklap biler.

Ilki bilen, adaty kitaphananyň berýän iň ýönekeý düşündirişlerine seredeliň.

(teswirlere ýene-de bir gezek sag boluň, ilki bilen bu blok gerek diýip pikir etmedim) Ilki bilen bellikleriň nämedigini ara alyp maslahatlaşalyň. Olaryň hersinde 2 sany esasy zerur parametr bar:
  • Saklaýyş görnüşi (saklamak);
  • Görkezilýän obýektiň görnüşi (Maksat).

Saklama görnüşi

“Saklaýyş görnüşi” diýmek, düşündirişimiziň synpyň içinde “diri galýan” tapgyryny aňladýarys. Her düşündirişde, “Saklamak syýasaty” synpynda görkezilen mümkin bolan “saklamak görnüşleriniň” diňe biri bar :
  • SÖCEGI - düşündiriş diňe kod ýazylanda ulanylýar we düzüji tarapyndan hasaba alynmaýar (ýagny, düzülenden soň ýatda saklanmaýar). Adatça islendik deslapky prosessorlar üçin (şertli) ýa-da düzüjä görkezmeler üçin ulanylýar
  • KLASS - düşündiriş düzülenden soň saklanýar, ýöne JVM tarapyndan hasaba alynmaýar (ýagny iş wagtynda ulanyp bolmaýar). Adatça koduňyzy plugin programmasy hökmünde ýükleýän islendik üçünji tarap hyzmatlary üçin ulanylýar
  • RUNTIME, düzülenden soň saklanýan we JVM tarapyndan ýüklenen düşündirişdir (meselem, programmanyň ýerine ýetirilişinde ulanylyp bilner). Programmanyň ýerine ýetirilmegine gönüden-göni täsir edýän kodda bellikler hökmünde ulanylýar (mysal şu ​​makalada ara alnyp maslahatlaşylar)

Aboveokarda görkezilen obýektiň görnüşi

Bu düşündiriş sözme-söz kabul edilmeli, sebäbi ... Java-da düşündirişler islendik zadyň üstünde kesgitlenip bilner (Meýdanlar, synplar, funksiýalar we ş.m.) we her düşündiriş üçin takyk kesgitlenip bilinjekdigi görkezilýär. Indi bu ýerde “bir zat” düzgüni ýok; düşündiriş aşakda görkezilenleriň hemmesinden ýokarda görkezilip bilner ýa-da diňe ElementType synpynyň zerur elementlerini saýlap bilersiňiz :
  • ANNOTATION_TYPE - başga bir düşündiriş
  • Gurluşykçy - synp konstruktory
  • SÖELGI - synp meýdançasy
  • LOCAL_VARIABLE - ýerli üýtgeýän
  • USUL - synp usuly
  • GAPY - paket paketiniň beýany
  • PARAMETER - usul parametri köpçülikleýin boş salam (@Annontation String param) {}
  • TYPE - synpyň ýokarsynda görkezilen
Umuman alanyňda, Java SE 1.8-e görä, adaty dil kitaphanasy bize 10 düşündiriş berýär. Bu makalada olaryň iň köp ýaýranlaryna serederis (hemmesi bilen gyzyklanýanlar? Javadoc-a hoş geldiňiz ):

@Override

Saklamak: SÖCEGI; Maksat: USUL. Bu düşündiriş, ýazylan usulyň ene synpdan miras galandygyny görkezýär. Her bir täze Java programmistiniň bu @Override yzygiderli itekleýän IDE ulanylanda duş gelýän ilkinji düşündiriş. Youtube-dan gelen mugallymlar köplenç: "päsgel bermezligi üçin pozuň" ýa-da: "Näme üçin bardygyny bilmän goýuň" maslahat berýärler. Aslynda, düşündiriş peýdaly däl: bu diňe bir bu synpda ilkinji gezek haýsy usullaryň kesgitlenendigini we ene-atalaryň eýýäm bardygyna düşünmäge mümkinçilik bermeýär (bu koduňyzyň okalmagyny şübhesiz ýokarlandyrýar), şeýle hem bu düşündiriş. Artykmaç funksiýany kesgitläniňizde ýalňyşmaýan “öz-özüni barlamak” bolup hyzmat edýär.

@Deprecated

Saklamak: Iş wagty; Maksat: Gurluşykçy, SÖELGI, LOCAL_VARIABLE, USUL, GURAMA, PARAMETER, TYPE. Bu düşündiriş, "köne" we önümiň geljekki wersiýalarynda aýrylyp bilinjek usullary, synplary ýa-da üýtgeýänleri kesgitleýär. Bu düşündiriş, adatça islendik API-leriň resminamalaryny ýa-da şol bir adaty Java kitaphanasyny okaýanlar bilen gabat gelýär. Käwagt bu düşündirişe ähmiýet berilmeýär, sebäbi ... hiç hili ýalňyşlyk döretmeýär we, esasan, durmuşa kän bir päsgel bermeýär. Şeýle-de bolsa, bu düşündirişiň esasy habary “bu funksiýany durmuşa geçirmek üçin has amatly usul tapdyk, ony ulanyň, köne usulyny ulanmaň” ýa-da başga bir zat - “funksiýanyň adyny üýtgetdik, ýöne bu şeýle, mirasa galdyrdyk ... ”(bu hem umuman erbet däl). Gysgaça aýdanyňda, @Deprecated-i görseň, asylgy zatlaryny düýbünden zerur bolmasa ulanmazlyga synanyşmak has gowudyr we könelen element tarapyndan ýerine ýetirilen meseläniň indi nähili ýerine ýetirilendigine düşünmek üçin resminamalary täzeden okamagyňyz mümkin. Mysal üçin, täze Sene (). GetYear () ulanmagyň ýerine Calendar.getInstance (). Get (Calendar.YEAR) ulanmak maslahat berilýär .

@SuppressWarnings

Saklamak: SÖCEGI; Maksat: TYPE, SÖELGI, USUL, PARAMETER, Gurluşykçy, LOCAL_VARIABLE Bu düşündiriş, görkezilen elemente degişli düzüjiniň duýduryşlarynyň çykyşyny öçürýär. SOURCE düşündirişi ýokarda görkezilen meýdanlar, usullar, synplar.

@Saklamak

Saklamak: RUNTIME; Maksat: ANNOTATION_TYPE; Bu düşündiriş, ýokarda görkezilen düşündirişiň "saklaýyş görnüşini" kesgitleýär. Hawa, bu düşündiriş hatda özi üçinem ulanylýar ... jady we bularyň hemmesi.

@ Maksat

Saklamak: RUNTIME; Maksat: ANNOTATION_TYPE; Bu düşündiriş, döredýän belligimiziň görkezilip bilinjek obýektiň görnüşini kesgitleýär. Hawa, bu hem özüňiz üçin ulanylýar, öwrenişiň ... Meniň pikirimçe, Java kitaphanasynyň adaty düşündirişleri bilen tanyşlygymyzy şu ýerde tamamlap bileris, sebäbi galanlary gaty seýrek ulanylýar we öz peýdalary bar bolsa-da, her kim olar bilen iş salyşmaly däl we düýbünden zerur däl. Adaty kitaphanadan belli bir düşündiriş hakda gürleşmegimi isleseňiz (ýa-da STL-e girmeýän @NotNull we @Nullable ýaly bellikler) teswirlerde ýazyň - ýa-da hoşniýetli ulanyjylar size jogap berer ýa-da Men ony görenimde ederin. Köp adam haýsydyr bir düşündiriş sorasa, men ony makala hem goşaryn.

RUNTIME bellikleriniň amaly ulanylyşy

Aslynda, meniň pikirimçe, bu ýeterlik teoretiki söhbet: geliň, botyň mysaly bilen tejribe geçeliň. Käbir sosial ulgam üçin bot ýazmak isleýärsiňiz diýeliň. VK, Facebook, Discord ýaly ähli esasy ulgamlarda bot ýazmaga mümkinçilik berýän öz API-leri bar. Şol torlar üçin, Java-da goşmak bilen, API-ler bilen işlemek üçin eýýäm ýazylan kitaphanalar bar. Şonuň üçin haýsydyr bir API ýa-da kitaphananyň işine göz aýlamarys. Bu mysalda bilmeli zatlarymyz, botymyzyň hakykatdanam ýerleşýän söhbetdeşligine iberilen habarlara jogap berip biler. .Agny, bir funksiýaly “MessageListener” synpymyz bar diýeliň :
public class MessageListener
{
    public void onMessageReceived(MessageReceivedEvent event)
    {
    }
}
Alnan habary gaýtadan işlemek üçin jogapkärdir. “MessageReceivedEvent” synpyndan bize gerek zat, alnan habaryň hatarydyr (mysal üçin, “Salam” ýa-da “Bot, salam”). Üns bermelidiris: dürli kitaphanalarda bu synplara başgaça diýilýär. Diskord üçin kitaphanany ulandym. Şeýlelik bilen, botyň “Bot” -dan başlaýan käbir buýruklara reaksiýa bildirmek isleýäris (dykyz ýa-da çekimsiz - özüňiz karar beriň: bu sapak üçin ol ýerde dykgat bolmaly däldir öýdýäris). .Agny, biziň wezipämiz şuňa meňzeş bir zat bilen başlar:
public void onMessageReceived(MessageReceivedEvent event)
{
    //Убираем чувствительность к регистру (БоТ, бОт и т.д.)
    String message = event.getMessage().toLowerCase();
    if (message.startsWith("бот"))
    {

    }
}
Indi bu ýa-da buýrugy ýerine ýetirmek üçin köp wariantymyz bar. Şübhesiz, ilki bilen buýrugy argumentlerinden aýyrmaly, ýagny ony bir massiwde bölmeli.
public void onMessageReceived(MessageReceivedEvent event)
{
    //Убираем чувствительность к регистру (БоТ, бОт и т.д.)
    String message = event.getMessage().toLowerCase();
    if (message.startsWith("бот"))
    {
        try
        {
            //получим массив {"Бот", "(команду)", "аргумент1", "аргумент2",... "аргументN"};
            String[] args = message.split(" ");
            //Для удобства уберем "бот" и отделим команду от аргументов
            String command = args[1];
            String[] nArgs = Arrays.copyOfRange(args, 2, args.length);
            //Получor command = "(команда)"; nArgs = {"аргумент1", "аргумент2",..."аргументN"};
            //Данный массив может быть пустым
        }
        catch (ArrayIndexOutOfBoundsException e)
        {
            //Вывод списка команд or Howого-либо messages
            //В случае если просто написать "Бот"
        }
    }
}
Bu kod böleklerinden gaça durup bilmeris, sebäbi buýrugy argumentlerden aýyrmak elmydama zerurdyr. Thenöne soň saýlamaly:
  • Eger (command.equalsIngnoreCase ("...")) et
  • Geçmek (buýruk)
  • Gaýtadan işlemegiň başga usullaryny ediň ...
  • Ora-da Annotasiýalaryň kömegine ýüz tutuň.
Indi bolsa, Annotasiýalary ulanmagyň amaly bölegine ýetdik. Geliň, wezipämiziň düşündiriş koduna seredeliň (elbetde başgaça bolup biler).
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//Указывает, что наша Аннотация может быть использована
//Во время выполнения через Reflection (нам How раз это нужно).
@Retention(RetentionPolicy.RUNTIME)

//Указывает, что целью нашей Аннотации является метод
//Не класс, не переменная, не поле, а именно метод.
@Target(ElementType.METHOD)
public @interface Command //Описание. Заметим, что перед interface стоит @;
{
    //Команда за которую будет отвечать функция (например "привет");
    String name();

     //Аргументы команды, использоваться будут для вывода списка команд
    String args();

     //Минимальное количество аргументов, сразу присвоor 0 (логично)
    int minArgs() default 0;

    //Описание, тоже для списка
    String desc();

     //Максимальное число аргументов. В целом не обязательно, но тоже можно использовать
    int maxArgs() default Integer.MAX_VALUE;

     //Показывать ли команду в списке (вовсе необязательная строка, но мало ли, пригодится!)
    boolean showInHelp() default true;

    //Какие команды будут считаться эквивалентными нашей
    //(Например для "привет", это может быть "Здаров", "Прив" и т.д.)
    //Под каждый случай заводить функцию - не рационально
    String[] aliases();

}
Möhüm! Her bir parametr funksiýa hökmünde (gabygyň kömegi bilen) beýan edilýär. Parametrler hökmünde diňe primitives, String , Enum ulanylyp bilner . Sanawy <String> args () ýazyp bilmersiňiz ; - ýalňyşlyk. Annotasiýany düşündirenimizden soň, “CommandListener” diýip bir synp döredeliň .
public class CommandListener
{
    @Command(name = "привет",
            args = "",
            desc = "Будь культурным, поздоровайся",
            showInHelp = false,
            aliases = {"здаров"})
    public void hello(String[] args)
    {
        //Какой-то функционал, на Ваше усмотрение.
    }

    @Command(name = "пока",
            args = "",
            desc = "",
            aliases = {"удачи"})
    public void bye(String[] args)
    {
         // Функционал
    }

    @Command(name = "помощь",
            args = "",
            desc = "Выводит список команд",
            aliases = {"help", "команды"})
    public void help(String[] args)
    {
        StringBuilder sb = new StringBuilder("Список команд: \n");
        for (Method m : this.getClass().getDeclaredMethods())
        {
            if (m.isAnnotationPresent(Command.class))
            {
                Command com = m.getAnnotation(Command.class);
                if (com.showInHelp()) //Если нужно показывать команду в списке.
                {
                    sb.append("Бот, ")
                       .append(com.name()).append(" ")
                       .append(com.args()).append(" - ")
                       .append(com.desc()).append("\n");
                }
            }
        }
        //Отправка sb.toString();

    }
}
Bir kiçijik oňaýsyzlygy bellemelidiris: t.c. Indi uniwersallyk ugrunda göreşýäris, ähli funksiýalarda resmi parametrleriň birmeňzeş sanawy bolmaly, şonuň üçin buýrugyň argumentleri bolmasa-da, funksiýanyň String [] args parametri bolmaly . Indi 3 buýrugy düşündirdik: salam, hoş, kömek. Indi munuň bilen bir zat etmek üçin “MessageListener” -imizi üýtgedeliň . Işiň amatlylygy we tizligi üçin buýruklarymyzy derrew HashMap -da saklarys :
public class MessageListner
{
    //Map который хранит How ключ команду
    //А How meaning функцию которая будет обрабатывать команду
    private static final Map<String, Method> COMMANDS = new HashMap<>();

    //Объект класса с командами (по сути нужен нам для рефлексии)
    private static final CommandListener LISTENER = new CommandListener();

    static
    {
       //Берем список всех методов в классе CommandListener
        for (Method m : LISTENER.getClass().getDeclaredMethods())
        {
            //Смотрим, есть ли у метода нужная нам Аннотация @Command
            if (m.isAnnotationPresent(Command.class))
            {
                //Берем an object нашей Аннотации
                Command cmd = m.getAnnotation(Command.class);
                //Кладем в качестве ключа нашей карты параметр name()
                //Определенный у нашей аннотации,
                //m — переменная, хранящая наш метод
                COMMANDS.put(cmd.name(), m);

                //Также заносим каждый элемент aliases
               //Как ключ указывающий на тот же самый метод.
                for (String s : cmd.aliases())
                {
                    COMMANDS.put(s, m);
                }
            }
        }
    }

    public void onMessageReceived(MessageReceivedEvent event)
    {

        String message = event.getMessage().toLowerCase();
        if (message.startsWith("бот"))
        {
            try
            {
                String[] args = message.split(" ");
                String command = args[1];
                String[] nArgs = Arrays.copyOfRange(args, 2, args.length);
                Method m = COMMANDS.get(command);
                if (m == null)
                {
                    //(вывод помощи)
                    return;
                }
                Command com = m.getAnnotation(Command.class);
                if (nArgs.length < com.minArgs())
                {
                    //что-то если аргументов меньше чем нужно
                }
                else if (nArgs.length > com.maxArgs())
                {
                    //что-то если аргументов больше чем нужно
                }
                //Через рефлексию вызываем нашу функцию-обработчик
                //Именно потому что мы всегда передаем nArgs у функции должен быть параметр
                //String[] args — иначе она просто не будет найдена;
                m.invoke(LISTENER, nArgs);
            }
            catch (ArrayIndexOutOfBoundsException e)
            {
                //Вывод списка команд or Howого-либо messages
                //В случае если просто написать "Бот"
            }
        }
    }
}
Toparlarymyzyň işlemegi üçin zerur zat. Indi täze buýruk goşmak täze däl, eger argumentleriň sanyny täzeden hasaplamaly we täze setirler goşup, täzeden ýazylmaly bolsa, täze bir ýagdaý däl. Indi buýruk goşmak üçin diňe CommandListener synpynda @Command düşündirişi bilen täze bir funksiýa goşmalydyrys we buýruk goşulýar, ýagdaýlar göz öňünde tutulýar, kömek awtomatiki usulda goşulýar. Bu meseläniň başga-da köp usul bilen çözülip bilinjekdigi jedelsiz. Hawa, düşündirişleriň / pikirlenmeleriň kömegi bilen edilip bilinjek hemme zat, olarsyz edilip bilner, ýeke-täk sorag amatlylyk, optimallyk we kod ölçegi, elbetde, ulanyp boljak iň az yşarat bar ýerinde Annotasiýa ýapmakdyr. haçan durmalydygyny bilmeli zatlaryň hemmesinde-de iň rasional wariant däl =). Emma şol bir görnüşi (ýöne birmeňzeş däl) kody gaýtalap boljak API-ler, kitaphanalar ýa-da programmalar ýazylanda, bellikler, şübhesiz, iň amatly çözgütdir.
Teswirler
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION