Dependency injection

Айсон :)

Разработчик
Пользователь
Сообщения
456
Решения
19
Полистал темы и наткнулся на интересную вещь

Что это такое? Можете привести примеры?
Почему это лучше геттеров, сеттеров и статиков?
 
Геттеры и сеттеры в общем случае ничего общего не имеют с пробросом зависимостей. Они просто реализуют один из принципов ООП – инкапсуляцию. Что касается статиков: их нужно использовать с осторожностью и при определенных сценариях, это вообще ломает логику ООП в каком-то смысле. То же самое касается реализации (анти-)паттерна Singleton, который очень часто вяжется со статикой.

Для того, чтобы правильно использовать статику, нужно прежде всего понимать, что она в сущности представляет и как на уровне языка работает (что позволяет делать – например, получать доступ к полям или методам без объекта класса, как инициализируется при запуске JVM и как ведет себя при создании новых объектов).

Про Dependency Injection в полной мере и по простому ответил BuseSo.
Я лишь бы добавил, что DI позволяет построить хорошо связную и при этом гибкую систему зависимостей внутри ПО архитектурно.

Советы по использованию статиков:
1. Для константных полей внутри классов. Поскольку поле имеет фиксированное значение независимо от состояния объекта, то можно объявить его как static. В случае, если в программе имеется множество объектов такого класса, и поле объявлено static, оно будет создано единожды при , а не создаваться в памяти каждый раз, когда создается объект.
Java:
(public|protected|private) static final Pattern NICKNAME_PATTERN = ...

2. Для утилитарных методов – методов, которые в своей логике никак не зависят от других объектов и их состояний.
В случае, если не зависеть от объектов невозможно и хочется сделать метод доступным без создания объекта его класса, то эти самые объекты можно просто пробрасывать в аргументах метода.
Java:
// Generates six-digit random code
public static String randomSixDigits() {
    return String.format("%06d", ThreadLocalRandom.current().nextInt(999999));
}

// Picks random element from provided List<T>
public static <T> T pickRandom(List<T> list) {
    return list.get(ThreadLocalRandom.current().nextInt(list.size()));
}

3. Для инициализации нескольких статичных объектов или выполнения one-shot действий при инициализации класса.
Java:
static {
    // Sets SLF4J logging provider for JBoss logging facade
    // System#setProperty(...) is actually a static method
    System.setProperty("org.jboss.logging.provider", "slf4j");
}
 
Последнее редактирование:
оно будет инициализировано единожды при старте JVM (даже если на этот класс никто не ссылается)
Это не так. Инициализация статических штук происходит при первом обращении, а не при загрузке класса
 
Только сейчас дошли руки до кода, сразу вопросы...
Java:
package me.itzisonn_.display;

import com.google.common.collect.Lists;
import me.itzisonn_.display.maincommand.DisplayCommand;
import me.itzisonn_.display.maincommand.DisplayTab;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.plugin.java.JavaPlugin;

import java.util.ArrayList;
import java.util.HashMap;

public class Display extends JavaPlugin {
    private final Utils utils = new Utils();

    public boolean isHookedPapi = false;
    public ArrayList<String> versions;
    public final HashMap<Integer, Entity> displays = new HashMap<>();



    @Override
    public void onEnable() {
        versions = Lists.newArrayList("1.19.4", "1.20", "1.20.1");
        saveDefaultConfig();

        new DisplayCommand();
        new DisplayTab();
        Bukkit.getPluginManager().registerEvents(new Utils(), this);

        if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) {
            Bukkit.getServer().getConsoleSender().sendMessage("[Display] Successfully hooked into PlaceholderAPI!");
            isHookedPapi = true;
        }

        utils.startTextUpdating();
        Bukkit.getServer().getConsoleSender().sendMessage("[Display] Enabled!");
        Bukkit.getServer().getConsoleSender().sendMessage(Bukkit.getVersion());

        utils.downloadEntities();
    }

    @Override
    public void onDisable() {
        utils.scheduler.cancel();
        Bukkit.getServer().getConsoleSender().sendMessage("[Display] Disabled!");
    }
}

Java:
package me.itzisonn_.display;

import me.clip.placeholderapi.PlaceholderAPI;
import me.itzisonn_.display.commands.Info;
import me.itzisonn_.display.commands.List;
import me.itzisonn_.display.maincommand.DisplayTab;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.TextDisplay;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.scheduler.BukkitTask;

import java.util.*;

public class Utils implements Listener {
private final Display display = new Display();
private final Info info = new Info();
private final List list = new List();
private final Config config;

public BukkitTask scheduler;



@EventHandler
    public void onChunckLoad(ChunkLoadEvent e) {
 for (Entity entity : e.getChunk().getEntities()) {
NamespacedKey namespacedKey = new NamespacedKey(display, "displayID");
            PersistentDataContainer data = entity.getPersistentDataContainer();

if (data.has(namespacedKey, PersistentDataType.INTEGER)) {
int displayID = Objects.requireNonNull(data.get(namespacedKey, PersistentDataType.INTEGER));
display.displays.put(displayID, entity);
Bukkit.getServer().getConsoleSender().sendMessage("[Display] Entity with ID " + displayID + " was downloaded!");
            }
        }
    }

public void downloadEntities() {
for (World world : Bukkit.getWorlds()) {
 for (Entity entity : world.getEntities()) {
NamespacedKey namespacedKey = new NamespacedKey(display, "displayID");
                PersistentDataContainer data = entity.getPersistentDataContainer();

if (data.has(namespacedKey, PersistentDataType.INTEGER)) {
int displayID = Objects.requireNonNull(data.get(namespacedKey, PersistentDataType.INTEGER));
display.displays.put(displayID, entity);
Bukkit.getServer().getConsoleSender().sendMessage("[Display] Entity with ID " + displayID + " was downloaded!");
                }
            }
        }
    }

public void startTextUpdating() {
int interval = config.getValue("textUpdateInterval");

if (interval != 0) {
scheduler = Bukkit.getServer().getScheduler().runTaskTimer(display, this::updateText, 0, interval * 20L);
        }
    }

public void updateText() {
for (World world : Bukkit.getWorlds()) {
 for (Entity entity : world.getEntities()) {
if (entity.getType() == EntityType.TEXT_DISPLAY) {
NamespacedKey namespacedKey = new NamespacedKey(display, "displayText");
                    PersistentDataContainer data = entity.getPersistentDataContainer();

if (data.has(namespacedKey, PersistentDataType.STRING)) {
String text = data.get(namespacedKey, PersistentDataType.STRING);

assert text != null;
if (display.isHookedPapi) {
((TextDisplay) entity).text(MiniMessage.miniMessage().deserialize(PlaceholderAPI.setPlaceholders(null, text)));
                        }
 else {
((TextDisplay) entity).text(MiniMessage.miniMessage().deserialize(text));
                        }
                    }
                }
            }
        }
    }

@EventHandler
    public void onInventoryClick(InventoryClickEvent e) {
if (!Objects.equals(e.getCurrentItem(), null)) {
if (info.isInventory(e.getClickedInventory())) {
assert e.getCurrentItem() != null;
NamespacedKey namespacedKey = new NamespacedKey(display, "displayItem");
                ItemMeta meta = e.getCurrentItem().getItemMeta();
                PersistentDataContainer data = meta.getPersistentDataContainer();

if (data.get(namespacedKey, PersistentDataType.STRING) != null) {
if (Objects.equals(data.get(namespacedKey, PersistentDataType.STRING), "exit")) {
 list.showList((Player) e.getWhoClicked());
                    }
                }

e.setCancelled(true);
} else if (list.isInventory(e.getClickedInventory())) {
assert e.getCurrentItem() != null;
NamespacedKey namespacedKey = new NamespacedKey(display, "displayItem");
                ItemMeta meta = e.getCurrentItem().getItemMeta();
                PersistentDataContainer data = meta.getPersistentDataContainer();

if (data.get(namespacedKey, PersistentDataType.STRING) != null && isInt(Objects.requireNonNull(data.get(namespacedKey, PersistentDataType.STRING)))) {
info.showInfo(Integer.parseInt(Objects.requireNonNull(data.get(namespacedKey, PersistentDataType.STRING))), (Player) e.getWhoClicked());
                }

e.setCancelled(true);
            }
        }
    }



public boolean isInt(String str) { return !str.equals("0") && str.length() <= 10 && str.matches("^\\d+$"); }
public boolean isDouble(String str) { return str != null && str.matches("[-+]?\\d*\\.?\\d+"); }
public boolean isFloat(String str) { return str != null && str.matches("-?[0-9]*\\.?[0-9]+"); }
}

Java:
package me.itzisonn_.display;

import me.itzisonn_.display.maincommand.DisplayTab;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.configuration.file.FileConfiguration;

public class Config {
private final Display display;
private final DisplayTab displayTab;

public Config(Display display, DisplayTab displayTab) {
this.display = display;
this.displayTab = displayTab;
    }

private FileConfiguration config = display.getConfig();



public Component getMsg(String path, String[] replaceTo) {
String msg = null;

if (path.equals("messages.errors.onlyPlayer")) {
msg = config.getString(path, "<red>Команду может выполнять только игрок!");
        }
if (path.equals("messages.errors.notFull")) {
msg = config.getString(path, "{prefix} <red>Неполная команда! Список команд: {help}");
msg = msg.replace("{help}", "/display help");
        }
if (path.equals("messages.errors.unknownAction")) {
msg = config.getString(path, "{prefix} <red>Неизвестный тип действия! Используйте: {subcommands}");
msg = msg.replace("{subcommands}", String.valueOf(displayTab.mainTabComplete())).replace(", ", " | ");
msg = msg.replace("{subcommands}", String.valueOf(displayTab.mainTabComplete())).replace("[", "").replace("]", "");
        }
if (path.equals("messages.errors.tooManyArguments")) {
msg = config.getString(path, "{prefix} <red>Слишком много аргументов!");
        }
if (path.equals("messages.errors.noPermission")) {
msg = config.getString(path, "{prefix} <red>У вас нет прав на выполнение данной команды!");
        }
if (path.equals("messages.errors.notFoundObjectType")) {
msg = config.getString(path, "{prefix} <red>Не найден тип объекта! Используйте: {types}");
msg = msg.replace("{types}", "block | item | text");
        }
if (path.equals("messages.errors.unknownObjectType")) {
msg = config.getString(path, "{prefix} <red>Неизвестный тип объекта! Используйте: {types}");
msg = msg.replace("{types}", "block | item | text");
        }
if (path.equals("messages.errors.notFoundId")) {
msg = config.getString(path, "{prefix} <red>Не найден ID объекта!");
        }
if (path.equals("messages.errors.invalidId")) {
msg = config.getString(path, "{prefix} <red>ID объекта должен быть числом!");
        }
if (path.equals("messages.errors.idAlreadyInUse")) {
msg = config.getString(path, "{prefix} <red>ID {id} уже используется!");
msg = msg.replace("{id}", replaceTo[0]);
        }
if (path.equals("messages.errors.idDoesNotExist")) {
msg = config.getString(path, "{prefix} <red>Объекта с ID {id} не существует!");
msg = msg.replace("{id}", replaceTo[0]);
        }
if (path.equals("messages.errors.notFoundEditType")) {
msg = config.getString(path, "{prefix} <red>Не найден тип редактирования! Используйте: {types}");
if (replaceTo[0].equalsIgnoreCase("block")) msg = msg.replace("{types}", "blocktype | glowing | scale");
if (replaceTo[0].equalsIgnoreCase("item")) msg = msg.replace("{types}", "itemtype | glowing | scale");
if (replaceTo[0].equalsIgnoreCase("text")) msg = msg.replace("{types}", "addline | setline | removeline | scale");
        }
if (path.equals("messages.errors.unknownEditType")) {
msg = config.getString(path, "{prefix} <red>Неизвестный тип редактирования! Используйте: {types}");
msg = msg.replace("{types}", "blocktype (itemtype) | glowing");
        }
if (path.equals("messages.errors.notFoundBlock")) {
msg = config.getString(path, "{prefix} <red>Не найден тип блока!");
        }
if (path.equals("messages.errors.unknownBlock")) {
msg = config.getString(path, "{prefix} <red>Неизвестный блок!");
        }
if (path.equals("messages.errors.notFoundItem")) {
msg = config.getString(path, "{prefix} <red>Не найден тип предмета!");
        }
if (path.equals("messages.errors.unknownItem")) {
msg = config.getString(path, "{prefix} <red>Неизвестный предмет!");
        }
if (path.equals("messages.errors.notFoundLineNumber")) {
msg = config.getString(path, "{prefix} <red>Не найден номер строки!");
        }
if (path.equals("messages.errors.invalidLineNumber")) {
msg = config.getString(path, "{prefix} <red>Номер строки должен быть числом!");
        }
if (path.equals("messages.errors.unknownLineNumber")) {
msg = config.getString(path, "{prefix} <red>Неизвестная строка!");
        }
if (path.equals("messages.errors.oneLine")) {
msg = config.getString(path, "{prefix} <red>Осталась последняя строка!");
        }
if (path.equals("messages.errors.notFoundText")) {
msg = config.getString(path, "{prefix} <red>Не найден текст!");
        }
if (path.equals("messages.errors.notFoundScales")) {
msg = config.getString(path, "{prefix} <red>Не найдены размеры!");
        }
if (path.equals("messages.errors.invalidScales")) {
msg = config.getString(path, "{prefix} <red>Неверный формат размеров!");
        }
if (path.equals("messages.errors.notFoundDimension")) {
msg = config.getString(path, "{prefix} <red>Не найдено измерение! Используйте: {types}");
msg = msg.replace("{types}", "overworld | the_nether | the_end");
        }
if (path.equals("messages.errors.unknownDimension")) {
msg = config.getString(path, "{prefix} <red>Неизвестное измерение! Используйте: {types}");
msg = msg.replace("{types}", "overworld | the_nether | the_end");
        }
if (path.equals("messages.errors.notFoundCoords")) {
msg = config.getString(path, "{prefix} <red>Не найдены координаты!");
        }
if (path.equals("messages.errors.invalidCoords")) {
msg = config.getString(path, "{prefix} <red>Неверный формат координат!");
        }

if (path.equals("messages.successfully.reloaded")) {
msg = config.getString(path, "{prefix} <green>Конфиг плагина успешно перезагружен!");
        }
if (path.equals("messages.successfully.created")) {
msg = config.getString(path, "{prefix} <green>Объект для отображения с ID {id} и типом {type} успешно создан!");
msg = msg.replace("{id}", replaceTo[0]);
msg = msg.replace("{type}", replaceTo[1]);
        }
if (path.equals("messages.successfully.deleted")) {
msg = config.getString(path, "{prefix} <green>Объект с ID {id} успешно удалён!");
msg = msg.replace("{id}", replaceTo[0]);
        }
if (path.equals("messages.successfully.edited")) {
msg = config.getString(path, "{prefix} <green>У объекта с ID {id} успешно изменён параметр {edittype} на {value}<green>!");
msg = msg.replace("{id}", replaceTo[0]);
msg = msg.replace("{edittype}", replaceTo[1]);
msg = msg.replace("{value}", replaceTo[2]);
        }
if (path.equals("messages.successfully.editedScale")) {
msg = config.getString(path, "{prefix} <green>У объекта с ID {id} успешно изменён размер на {scalex}, {scaley}, {scalez}");
msg = msg.replace("{id}", replaceTo[0]);
msg = msg.replace("{scalex}", replaceTo[1]);
msg = msg.replace("{scaley}", replaceTo[2]);
msg = msg.replace("{scalez}", replaceTo[3]);
        }
if (path.equals("messages.successfully.editedAddline")) {
msg = config.getString(path, "{prefix} <green>Объекту с ID {id} успешно добавлена строка под номером {linenumber} с значением {text}<reset><green>!");
msg = msg.replace("{id}", replaceTo[0]);
msg = msg.replace("{linenumber}", replaceTo[1]);
msg = msg.replace("{text}", replaceTo[2]);
        }
if (path.equals("messages.successfully.editedSetline")) {
msg = config.getString(path, "{prefix} <green>У объекта с ID {id} успешно изменена строка под номером {linenumber} на значение {text}<reset><green>!");
msg = msg.replace("{id}", replaceTo[0]);
msg = msg.replace("{linenumber}", replaceTo[1]);
msg = msg.replace("{text}", replaceTo[2]);
        }
if (path.equals("messages.successfully.editedRemoveline")) {
msg = config.getString(path, "{prefix} <green>У объекта с ID {id} успешно удалена строка под номером {linenumber}<green>!");
msg = msg.replace("{id}", replaceTo[0]);
msg = msg.replace("{linenumber}", replaceTo[1]);
        }
if (path.equals("messages.successfully.teleportedCoords")) {
msg = config.getString(path, "{prefix} <green>Объект с ID {id} успешно перемещён на координаты {x} {y} {z} в мире {world}!");
msg = msg.replace("{id}", replaceTo[0]);
msg = msg.replace("{x}", replaceTo[1]);
msg = msg.replace("{y}", replaceTo[2]);
msg = msg.replace("{z}", replaceTo[3]);
msg = msg.replace("{world}", replaceTo[4]);
        }
if (path.equals("messages.successfully.teleportedHere")) {
msg = config.getString(path, "{prefix} <green>Объект с ID {id} успешно перемещён на ваши координаты!");
msg = msg.replace("{id}", replaceTo[0]);
        }
if (path.equals("messages.successfully.teleportedTo")) {
msg = config.getString(path, "{prefix} <green>Вы были успешно перемещены на координаты объекта с ID {id}!");
msg = msg.replace("{id}", replaceTo[0]);
        }
if (path.equals("messages.successfully.changedID")) {
msg = config.getString(path, "{prefix} <green>У объекта с ID {id} ID был изменен на {newid}!");
msg = msg.replace("{id}", replaceTo[0]);
msg = msg.replace("{newid}", replaceTo[1]);
        }


if (msg != null && msg.contains("{prefix}")) {
msg = msg.replace("{prefix}", config.getString("messages.prefix", "<#6d6d6d>[<gradient:#fdd134:#fb630e>Display</gradient><#6d6d6d>]<reset>"));
        }

assert msg != null;
return MiniMessage.miniMessage().deserialize(msg);
    }



public void reloadConfig() {
config = display.getConfig();
    }

public int getValue(String path) {
int value = 1;

if (path.equals("textUpdateInterval")) {
value = config.getInt(path, 1);
        }

 return value;
    }
}

В классе Config у меня ошибка: "Variable display might not have been initialized" (17стр)
В классе Utils: "Variable config might not have been initialized" (30стр)

Это ошибки от самой Intellij


Можете всё-таки объяснить, как это сделать? (Перелазил интернет - нет наглядного примера с классами)
 
Java:
public class Config {
    private final Display display;
    private final DisplayTab displayTab;
    private final FileConfiguration config;

    public Config(Display display, DisplayTab displayTab) {
        this.display = display;
        this.displayTab = displayTab;
        this.config = display.getConfig();
     }

    // ...
В случае с Utils.java переменная не инициализируется, ей нужно задать значение либо сразу в поле, либо в конструкторе класса.
public class Utils implements Listener {
private final Display display = new Display();
Если здесь Display – это Display.java, то это неправильно. Не нужно создавать экземпляр класса каждый раз, когда он нужен (тем более если это класс плагина). Этот объект нужно передавать в конструкторах классов, где он требуется. Это и есть простейшая реализация Dependency Injection.
Java:
public class Utils implements Listener {
    private final Display display;
    private final Config config;
    
    private final Info info = new Info();
    private final List list = new List();

    public BukkitTask scheduler;
    
    public Utils(Display display) {
        this.display = display;
        this.config = ?
    }
    
    // ...
 
Последнее редактирование:
Спасибо.

Java:
public abstract class AbstractCommand implements CommandExecutor {
    public AbstractCommand(String command, Display display) {
        PluginCommand pluginCommand = display.getCommand(command);

        if (pluginCommand != null) {
            pluginCommand.setExecutor(this);
        }
    }

    public abstract void executeCommand(CommandSender sender, String[] args);

    @Override
    public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
        executeCommand(sender, args);
        return true;
    }
}

Java:
public class DisplayCommand extends AbstractCommand {
    private final ChangeID changeID;
    private final Create create;
    private final Delete delete;
    private final Edit edit;
    private final Help help;
    private final Info info;
    private final List list;
    private final Reload reload;
    private final Tpcoords tpcoords;
    private final Tpto tpto;
    private final Tphere tphere;
    private final Config config;

    public DisplayCommand(ChangeID changeID, Create create, Delete delete, Edit edit, Help help, Info info, List list, Reload reload, Tpcoords tpcoords, Tpto tpto, Tphere tphere, Config config) {
        super("display", !!!);

        this.changeID = changeID;
        this.create = create;
        this.delete = delete;
        this.edit = edit;
        this.help = help;
        this.info = info;
        this.list = list;
        this.reload = reload;
        this.tpcoords = tpcoords;
        this.tpto = tpto;
        this.tphere = tphere;
        this.config = config;
    }

    public Player player;



    @Override
    public void executeCommand(CommandSender sender, String[] args) {
        //...
    }

Правильно ли я понимаю, что надо в public DisplayCommand(ChangeID changeID,...) вставить Display display и использовать это в super("display", display); ?
 
Сделал. В консоли ошибка:
Код:
[12:50:58 ERROR]: [ModernPluginLoadingStrategy] Could not load plugin 'Display-1.3.jar' in folder 'plugins'
org.bukkit.plugin.InvalidPluginException: Abnormal plugin type
        at org.bukkit.plugin.java.PluginClassLoader.<init>(PluginClassLoader.java:92) ~[paper-api-1.19.4-R0.1-SNAPSHOT.jar:?]
        at io.papermc.paper.plugin.provider.type.spigot.SpigotPluginProvider.createInstance(SpigotPluginProvider.java:123) ~[paper-1.19.4.jar:git-Paper-538]
        at io.papermc.paper.plugin.provider.type.spigot.SpigotPluginProvider.createInstance(SpigotPluginProvider.java:35) ~[paper-1.19.4.jar:git-Paper-538]
        at io.papermc.paper.plugin.entrypoint.strategy.modern.ModernPluginLoadingStrategy.loadProviders(ModernPluginLoadingStrategy.java:116) ~[paper-1.19.4.jar:git-Paper-538]
        at io.papermc.paper.plugin.storage.SimpleProviderStorage.enter(SimpleProviderStorage.java:39) ~[paper-1.19.4.jar:git-Paper-538]
        at io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler.enter(LaunchEntryPointHandler.java:36) ~[paper-1.19.4.jar:git-Paper-538]
        at org.bukkit.craftbukkit.v1_19_R3.CraftServer.loadPlugins(CraftServer.java:424) ~[paper-1.19.4.jar:git-Paper-538]
        at net.minecraft.server.dedicated.DedicatedServer.initServer(DedicatedServer.java:273) ~[paper-1.19.4.jar:git-Paper-538]
        at net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:1104) ~[paper-1.19.4.jar:git-Paper-538]
        at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:320) ~[paper-1.19.4.jar:git-Paper-538]
        at java.lang.Thread.run(Thread.java:1589) ~[?:?]
Caused by: java.lang.InstantiationException: me.itzisonn_.display.Display
        at java.lang.Class.newInstance(Class.java:678) ~[?:?]
        at org.bukkit.plugin.java.PluginClassLoader.<init>(PluginClassLoader.java:88) ~[paper-api-1.19.4-R0.1-SNAPSHOT.jar:?]
        ... 10 more
Caused by: java.lang.NoSuchMethodException: me.itzisonn_.display.Display.<init>()
        at java.lang.Class.getConstructor0(Class.java:3641) ~[?:?]
        at java.lang.Class.newInstance(Class.java:665) ~[?:?]
        at org.bukkit.plugin.java.PluginClassLoader.<init>(PluginClassLoader.java:88) ~[paper-api-1.19.4-R0.1-SNAPSHOT.jar:?]
        ... 10 more
 
Если у класса плагина есть конструктор и логика в нем, то его нужно убрать и всю логику оттуда перенести в метод onEnable().
То есть?
Java:
public class Display extends JavaPlugin {
    private final ChangeID changeID;
    private final Create create;
    private final Delete delete;
    private final Edit edit;
    private final Help help;
    private final Info info;
    private final List list;
    private final Reload reload;
    private final Tp tp;
    private final Config config;
    private final Utils utils;

    /*public Display(ChangeID changeID, Create create, Delete delete, Edit edit, Help help, Info info, List list, Reload reload, Tp tp, Config config, Utils utils) {
        this.changeID = changeID;
        this.create = create;
        this.delete = delete;
        this.edit = edit;
        this.help = help;
        this.info = info;
        this.list = list;
        this.reload = reload;
        this.tp = tp;
        this.config = config;
        this.utils = utils;
    }*/



    @Override
    public void onEnable(ChangeID changeID, Create create, Delete delete, Edit edit, Help help, Info info, List list, Reload reload, Tp tp, Config config, Utils utils) {
        this.changeID = changeID;
        this.create = create;
        this.delete = delete;
        this.edit = edit;
        this.help = help;
        this.info = info;
        this.list = list;
        this.reload = reload;
        this.tp = tp;
        this.config = config;
        this.utils = utils;
       
        //...
    }
}

Ошибку показывает
 
Ошибку показывает
Я не совсем понимаю, что ты хочешь сделать. onEnable() не принимает никаких аргументов, это метод класса JavaPlugin, который просто переопределяется в соответствии с тем, что необходимо сделать плагину при запуске.
Конструктор ты убрал и это правильно. Теперь, в зависимости от того, что тебе требуется сделать, в методе onEnable() нужно задать значения всем переменным класса, причем поля в этом случае не получится сделать final и в этом ничего такого нет, они все равно приватные.
 
Я не совсем понимаю, что ты хочешь сделать. onEnable() не принимает никаких аргументов, это метод класса JavaPlugin, который просто переопределяется в соответствии с тем, что необходимо сделать плагину при запуске.
Конструктор ты убрал и это правильно. Теперь, в зависимости от того, что тебе требуется сделать, в методе onEnable() нужно задать значения всем переменным класса, причем поля в этом случае не получится сделать final и в этом ничего такого нет, они все равно приватные.
Как мне задать значения для переменных, если я убрал конструктор?

Java:
public class Display extends JavaPlugin {
    private ChangeID changeID;
    private Create create;
    private Delete delete;
    private Edit edit;
    private Help help;
    private Info info;
    private List list;
    private Reload reload;
    private Tp tp;
    private Config config;
    private Utils utils;

    /*public Display(ChangeID changeID, Create create, Delete delete, Edit edit, Help help, Info info, List list, Reload reload, Tp tp, Config config, Utils utils) {
        this.changeID = changeID;
        this.create = create;
        this.delete = delete;
        this.edit = edit;
        this.help = help;
        this.info = info;
        this.list = list;
        this.reload = reload;
        this.tp = tp;
        this.config = config;
        this.utils = utils;
    }*/



    @Override
    public void onEnable() {
        //...
    }
}
 
Назад
Сверху Снизу