java .lang.InstantiationError. Класс становится абстрактным - PullRequest
0 голосов
/ 07 января 2020

В настоящее время я работаю над плагином Bukkit для Minecraft и получаю ошибку java .lang.InstantiationError при попытке создать новый объект. Трассировка стека выглядит следующим образом:

Caused by: java.lang.InstantiationError: fancyui.craterhater.components.FancyComponent
    at fancyui.craterhater.uibuilder.ComponentMaker.getComponent(ComponentMaker.java:13) ~[?:?]
    at fancyui.craterhater.uibuilder.Editor_Page_0.getComponents(Editor_Page_0.java:40) ~[?:?]
    at fancyui.craterhater.uibuilder.Editor$1.call(Editor.java:36) ~[?:?]
    at fancyui.craterhater.masterfancyui.FancyUI.openInventory(FancyUI.java:195) ~[?:?]
    at fancyui.craterhater.uibuilder.Editor.createEditorGUI(Editor.java:236) ~[?:?]
    at fancyui.craterhater.commandhandler.MasterCommand$2.call(MasterCommand.java:69) ~[?:?]
    at fancyui.craterhater.commandhandler.CECommand.playerExecutes(CECommand.java:105) ~[?:?]
    at fancyui.craterhater.commandhandler.CECommand.checkPlayerExecutes(CECommand.java:98) ~[?:?]
    at fancyui.craterhater.commandhandler.MasterCommand.onCommand(MasterCommand.java:153) ~[?:?]
    at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) ~[1.8.jar:git-Spigot-870264a-0a645a2]
    ... 15 more

В строке 13 класса ComponentMaker просто говорится:

FancyComponent fancyComponent = new FancyComponent();

Я провел некоторую отладку и решил напечатать следующее:

System.out.println(FancyComponent.class.toGenericString());

Это напечатано;

public abstract class fancyui.craterhater.components.FancyComponent

Пока класс FancyComponent не является абстрактным. Вот класс FancyComponent:

public class FancyComponent {

    //FancyComponent class represents the individual items placed in a FancyUI. 
    //It handles things such as animation, itemstack building and event handling whilst
    //allowing the FancyUI to handle loading and deleting of these components.
    //FancyComponents are added to the FancyUI by the user of the API using LoadFunctions.
    //They can also be generated from a FancyUI file.

    private FancyLocation fancyLocation;
    private FancyItemStack fancyItemStack;
    private FancyDisplayType fancyDisplayType;
    private String identifier = null;
    private int ID = 0;
    private int basicSlot = 0;
    private boolean copied;

    public FancyComponent() {
        fancyDisplayType = FancyDisplayType.DYNAMIC;
    }

    public FancyComponent copy(FancyLocation newLocation) {
        FancyComponent newComponent = new FancyComponent();
        newComponent.setDisplayType(fancyDisplayType);
        newComponent.setID(ID);
        newComponent.setFancyItemStack(fancyItemStack);
        newComponent.setFancyLocation(newLocation);
        newComponent.setAttributes(attributes);
        newComponent.setIdentifier(identifier);
        return newComponent;
    }


    //Method gets called when FancyUI decides to load in new FancyComponents.
    //This happens when openInventory gets called and new components are generated.
    //This method should start future animations. It should also handle ItemStack placement.
    //The boolean here represents whether or not it has succesfully been added. This is used in the
    //FancyUI in order to keep track of all active components and not the once off-screen.
    public boolean addToUI(Inventory inventory, Player p, FileConfiguration fc, FileConfiguration fc2) {
        if(fancyLocation == null) {return false;}

        return addToUI(inventory, p, fancyLocation, fc, fc2);
    }

    public boolean addToUI(Inventory inventory, Player p, FancyLocation fancyLocation, FileConfiguration fc, FileConfiguration fc2) {
        if(fancyItemStack == null) {return false;}

        FancyUI fancyUI = fancyLocation.getFancyUI();
        FancyLocation masterFancyLocation = fancyUI.getFancyData().getCurrentFancyLocation();

        if(!fancyLocation.isInView(masterFancyLocation, fancyDisplayType)) {return false;}

        int basicSlot = fancyLocation.getBasicLocation(masterFancyLocation.getX(), masterFancyLocation.getY(), fancyDisplayType);

        if(basicSlot < 0 || basicSlot >= inventory.getSize()) {return false;}

        this.basicSlot = basicSlot;

        ItemStack itemStack = fancyItemStack.buildItemStack(p,fc2);

        if(fc != null) {
            if(fc.contains("Components."+identifier+".Animations")) {
                for(String animation : fc.getConfigurationSection("Components."+identifier+".Animations").getKeys(false)) {
                    if(fc.getBoolean(("Components."+identifier+".Animations."+animation+".continious"))){
                        List<String> frames = new ArrayList<>();
                        if(fc.contains("Components."+identifier+".Animations."+animation+".animation")) {
                            frames = fc.getStringList("Components."+identifier+".Animations."+animation+".animation");
                        }

                        int interval = fc.getInt("Components."+identifier+".Animations."+animation+".interval");

                        if(interval < 1) {
                            interval = 2;
                        }

                        int position = fc.getInt("Components."+identifier+".Animations."+animation+".position");
                        boolean continious = fc.getBoolean("Components."+identifier+".Animations."+animation+".continious");
                        boolean reverse = fc.getBoolean("Components."+identifier+".Animations."+animation+".reverse");

                        fancyItemStack.startAnimation(frames, p, interval, position, this, continious, reverse);
                        break;
                    }
                }
            }
        }

        if(fancyLocation.getFancyUI().getFancyData().isPlayerInventory()) {
            if(fancyItemStack.getCustomName().getFancyStringAnimations().length > 0) {
                fancyItemStack.startAnimation(fancyItemStack.getCustomName().getFancyStringAnimations()[0].getFrames(), p, 4, 0, this, true, false);
            }
        }

        inventory.setItem(basicSlot, itemStack);
        return true;
    }

    //Method to reload just this component. It is used when cycling through fancyLore. If a function makes changes
    //to other components the reload method in the FancyUI has to be called in order to fully reload a page.
    public void reload(Player p) {
        FileConfiguration fc = DataHandler.getFile(96,p.getUniqueId().toString(), false, "Data", "Users");
        ItemStack itemStack = fancyItemStack.buildItemStack(p,fc);

        if(fancyLocation == null) {
            return;
        }

        if(fancyLocation.getFancyUI().getFancyData().isPlayerInventory()) {
            p.getInventory().setItem(basicSlot, itemStack);
            return;
        }

        fancyLocation.getFancyUI().getFancyData().getInventory().setItem(basicSlot, itemStack);
    }


    //Method gets called when FancyUI deletes all information on other FancyComponents.
    //This happens when openInventory gets called and new components are generated.
    //Make sure that this method cleans up future animations so they don't go around throwing nullpointers.
    //The ItemStack itself is removed automatically by the FancyUI.
    public void notifyOfDeletion() {
        fancyItemStack.stopAnimating();
    }

    //Attributes are pieces of code written by the user of the API in order to have certain things
    //happen at certain events such as ON_CLICK or ON_DROP etc.
    private List<Attribute> attributes = new ArrayList<>();

    public void addAttribute(Attribute attribute) {
        attributes.add(attribute);
    }

    public List<Attribute> getAttributes(){
        return attributes;
    }

    public void setAttributes(List<Attribute> attributes) {
        this.attributes = attributes;
    }

    //Method to identify which Attributes need to run at these specific occasions. These occasions
    //may include things suchs as ON_CLICK or ON_1 just to name a few. This method consists of two
    //distinct parts. The first part handles all generated components which have scripts assigned to them
    //and the second part handles all components that have been generated by the plugin itself. And thus
    //do not have scripts assigned to them.
    public void handleEvent(FileConfiguration fc, FileConfiguration fc2, FunctionParams params, AttributeOccasion... attributeOccasions) {
        //The 'identifier' is a tag all generated components get. It is unique to all components. 
        //Non-generated components do not have this tag and thus we can check for null to see whether or not
        //it is generated.
        if(identifier != null) {
            if(fc.contains("Components."+identifier+".Scripts")) {
                for(String script : fc.getConfigurationSection("Components."+identifier+".Scripts").getKeys(false)) {
                    if(fc.contains("Components."+identifier+".Scripts."+script+".events")) {
                        List<String> scriptLines = fc.getStringList("Components."+identifier+".Scripts."+script+".script");
                        for(String event : fc.getStringList("Components."+identifier+".Scripts."+script+".events")) {
                            A: for(AttributeOccasion attributeOccasion : attributeOccasions) {
                                if(attributeOccasion.name().equalsIgnoreCase(event)) {
                                    fancyLocation.getFancyUI().getScriptParser().executeScript(params.getPlayer(), scriptLines, FancyUI.fancyUI.get(params.getPlayer().getUniqueId()), params.getFancyComponent(), fc2, false);
                                    break A;
                                }
                            }
                        }
                    }
                }
            }

            if(fc.contains("Components."+identifier+".Animations")) {
                for(String script : fc.getConfigurationSection("Components."+identifier+".Animations").getKeys(false)) {
                    if(fc.contains("Components."+identifier+".Animations."+script+".events")) {
                        for(String event : fc.getStringList("Components."+identifier+".Animations."+script+".events")) {
                            A: for(AttributeOccasion attributeOccasion : attributeOccasions) {
                                if(attributeOccasion.name().equalsIgnoreCase(event)) {
                                    List<String> frames = new ArrayList<>();
                                    if(fc.contains("Components."+identifier+".Animations."+script+".animation")) {
                                        frames = fc.getStringList("Components."+identifier+".Animations."+script+".animation");
                                    }

                                    int interval = fc.getInt("Components."+identifier+".Animations."+script+".interval");

                                    if(interval < 1) {
                                        interval = 2;
                                    }

                                    int position = fc.getInt("Components."+identifier+".Animations."+script+".position");

                                    boolean continious = fc.getBoolean("Components."+identifier+".Animations."+script+".continious");
                                    boolean reverse = fc.getBoolean("Components."+identifier+".Animations."+script+".reverse");
                                    fancyItemStack.startAnimation(frames, params.getPlayer(), interval, position, this, continious, reverse);
                                    break A;
                                }
                            }
                        }
                    }
                }
            }
        }

        //Handles all components generated by the plugin as well as generated components from file if this component is inside of an editor.
        //If inside an editor generated components will have some attributes linked to them by the plugin. If not inside an editor, generated components
        //will not have any attributes linked to them. 
        A:for(Attribute attribute : attributes) {
            for(AttributeOccasion attributeOccasion : attribute.getAttributeOccasions()){
                for(AttributeOccasion attributeOccasion2 : attributeOccasions) {
                    if(attributeOccasion.equals(attributeOccasion2)) {
                        attribute.getAttributeFunction().call(params);
                        continue A;
                    }
                }
            }
        }
    }

    //This method is used to move the cursor in list cycleables. 
    public void performCursorMove(int delta, Player p) {
        if(fancyItemStack == null) {return;}
        FancyLore fancyLore = fancyItemStack.getFancyLore();
        if(fancyLore == null) {return;}

        fancyLore.moveCursor(delta, p);
    }

    public void setCursorPosition(int n, Player p) {
        if(fancyItemStack == null) {return;}
        FancyLore fancyLore = fancyItemStack.getFancyLore();
        if(fancyLore == null) {return;}

        fancyLore.setCursorPosition(n, p);
    }

    public int getSlot() {
        return basicSlot;
    }

    public FancyLocation getFancyLocation() {
        return fancyLocation;
    }

    public FancyItemStack getFancyItemStack() {
        return fancyItemStack;
    }

    public void setFancyItemStack(FancyItemStack fancyItemStack) {
        this.fancyItemStack = fancyItemStack;
    }

    public void setFancyLocation(FancyLocation fancyLocation) {
        this.fancyLocation = fancyLocation;
    }

    public void setDisplayType(FancyDisplayType fancyDisplayType) {
        this.fancyDisplayType = fancyDisplayType;
    }

    public void setIdentifier(String identifier) {
        this.identifier = identifier;
    }

    public String getIdentifier() {
        return identifier;
    }

    public void setIsCopied(boolean copied) {
        this.copied = copied;
    }

    public boolean isCopied() {
        return copied;
    }

    public void setID(int ID) {
        this.ID = ID;
    }

    public int getID() {
        return ID;
    }

    public FancyDisplayType getFancyDisplayType() {
        return fancyDisplayType;
    }
}

Странно то, что это не происходит в более поздних версиях Spigot. Я проверил это на 1.8, 1.9 и 1.15, и ошибка происходит на 1.8 и 1.9, но не на 1.15. Любая помощь будет оценена.

Похоже, только не выдает ошибку в последней версии (1.15). Все остальные версии выдают ошибку.

После нескольких часов тестирования я решил скопировать и вставить код проблемного c класса в новый класс. Я переименовал все ссылки на этот класс. Это исправило мою проблему, но я не особенно доволен ею, тем более что оригинальное имя все еще вызывает ошибку. Поэтому, если я переименую новый класс в старое имя, снова появится ошибка.

...