Solved Cannot instantiate a class from class shown as abstract class whilst being normal class

Discussion in 'Spigot Plugin Development' started by Nuubles, Jul 18, 2019.

  1. As I'm new to storing and handling Java classes like this please spare me if I'm doing something wrong. As a sidenote also the code is still under development so it may have some inconsistencies. So to clear up the structure and why it is like this is as follows:
    TimeLevel: Contains 1-N Requirements and Executors
    Requirement and Executor: Abstract classes which all store the newly created subclasses into a map by calling the register(String key) function.

    Main problem: When retrieving the classes from Requirement or Executor and trying to create new instances calling their constructor Java throws InstantiationException as the Requirement and Executor classes are both abstract (as in it stores the class (subclass) in a map as cast to the superclass (Requirement or Executor). How could I create a new instance of a given class stored into a map in superclass using the superclass as the map value?

    Here's the code which I use to create a new instance of a class:
    section: ConfigurationSection (correct section is used)
    REQUIREMENTS: String "requirements" -> used as path
    requirementKey: String x to the correct section in config such as level-starter

    Code (Java):
    // get the class which will be used in creating a new object
                    Class<? extends Requirement<?>> reqClass = (Class<? extends Requirement<?>>) Requirement.getRequirement(requirementKey);
                    // get the constructor
                    Constructor<? extends Requirement<?>> ctor = reqClass.getConstructor(ConfigurationSection.class, String.class, String.class);
                   
                    // create a new instance of the given class
                    Requirement<?> req = ctor.newInstance(section, REQUIREMENTS, requirementKey); // ERROR HERE
     

    Here's a part of the requirement superclass which stores the subclasses:
    Code (Java):
    public abstract class Requirement<T> {
        private String path;
        private ConfigurationSection config;
        @SuppressWarnings("rawtypes")
        private final static HashMap<String, Class<? extends Requirement>> requirements =
                new HashMap<String, Class<? extends Requirement>>();
       
        /**
         *
         * @param path Path to the key
         * @param key requirements key
         */

        public Requirement(ConfigurationSection config, String path, String key) {
            this.path = path + "." + key;
            this.config = config;
        }
       
       
        public static final void register(String key) {
            requirements.put(key, Requirement.class);
        }
       
       
        /**
         * Returns all of the requirements ever created
         * @return requirements created
         */

        @SuppressWarnings("rawtypes")
        public static final Class<? extends Requirement> getRequirement(String key) {
            return requirements.get(key);
        }
       
       
        /**
         * Check if there is a requirement class created
         * @param key key to the requirement class
         * @return true if the requirement class exists, false otherwise
         */

        public static final boolean hasRequirement(String key) {
            return requirements.containsKey(key);
        }


        /**
         * Is this requirement met
         * @param uuid uuid of the player being checked
         * @return true if the requirement is met, false otherwise
         */

        public abstract boolean isRequirementMet(Player player);
    }

    As far as I know, the exception is thrown because Java cannot instantiate a new object from an abstract class (obviously) but how would I create an object from a normal class which is shown as an abstract class?
     
  2. Implement the abstract class as a non-abstract class and instantiate the implementation through the new keyword.
     
    • Useful Useful x 1
  3. Thank you! Although this didn't exactly solve my problem I got an idea of how to solve it thanks to your comment!

    The classes are still abstract but instead of taking the class from the abstract class in register(String key) I replaced it with register(String key, Class<? extends Requirement> clazz) so now instead of the class trying to register from the superclass the implementing class now has to register it by itself which mostly uses static public static void register(String key) which in turn calls the superclass with register(key, ImplementingClass.class).
    The above mentioned now allows the map to store classes which implement the abstract class instead of just storing from the abstract class which results in the class being in memory being abstract.