Java: how to have an array of subclass types?
Asked Answered
K

4

6

Say I have a super class "Animal" and subclasses "Cat", Dog, Bird". Is there a way to have an array of subclass type rather than class instances with which I'll be able to instantiate instances of each possible subclass?

To simplify, I want this:

Pseudo code: For each possible subclass of "Animal": create an instance of that class.

How can I do that?

Edit: I don't want an array of instances of these subclasses, I want an array of object type.

Knighterrant answered 19/7, 2013 at 3:0 Comment(11)
it's not clear your questionIndigestible
What, you guys don't make Animal and Employee classes all the time?Electron
It is not an assignment. I am using animals to make the problem easier to understand. @Indigestible Basically I want to create an array of each possible different subclass of superclass "MySuperClass".Kwasi
ii don't see the problem.. subclasses are made in static way so you know what are the subclasses just make a factory to create them..Indigestible
AFAIK, there is no way to programmatically discover all subclasses of a given type.Binns
@OliCharlesworth what about this code.google.com/p/reflectionsIndigestible
@MickaelBergeronNéron you need to add a example so people can get understand it well.As for as I understood that you want to create a array/list of subclass (Lets say Cat) and store all the subclass objects(it would be a Cat ,Dog or anyother subclass) in cats list/arrayTruckle
@MickaelBergeronNéron IF you want this then this is not possible, in case you use generics because it is against polymorphism.But it is possible in case, if you dont define the type of list.But in this case , casting would be overhead and you have to check the type of object instanceOf on every indexTruckle
@nachokk: If that works in practice, then I stand corrected ;)Binns
What I want is an array of object type. Then I want to use that array to instantiate a single instance of each of these object.Kwasi
@MickaelBergeronNéron See the edited answer.Doesn't it help you?Truckle
T
3

After OP's comment
THERE IS NO WAY TO GET ALL SUBTYPES OF A CLASS even using reflection.
But you can do it by another way , you can say which is the only but longest way.

  • Get a list of names of all classes that exist on the class path
  • Load each class and test to see if it is a subclass or implementor of the desired class or interface



Answer before OP's comment

As your question is not clear yet but I guess you want to use array or Collection which will store all of the instances even it is the instance of superclass or subclass.
Then I guess you need to do like this.

List<Object> list = new ArrayList<Object>();
         list.add(new Cat());
         list.add(new Dog());
         list.add(new Animal());
         list.add(new Cat());

         for (int i = 0; i < list.size(); i++) {

             if(list.get(i) instanceof Cat){
                 System.out.println("Cat at "+i);
             }else if(list.get(i) instanceof Dog){
                 System.out.println("Dog at "+i);
             }else if(list.get(i) instanceof Animal){
                 System.out.println("Animal at "+i);
             }
        }

This code is tested
Note: Keep in mind that Don't place parent class check like in case of example code (list.get(i) instanceof Animal) at top, otherwise it will pass both cases (if checks are only if-if-if) or skip one case(and always return the object as a Animal if checks are if-else if-else if) (list.get(i) instanceof Animal) and (list.get(i) instanceof Cat) If the returning object is a Cat object.

Truckle answered 19/7, 2013 at 3:32 Comment(1)
What I want is an array of object type, which I can use to instantiate objects of these types. If that is possible that is.Kwasi
A
7

You can use Ploymorphism to achieve that.

Animal[] animalArray = new Animal[10];
animalArray[0] = new Dog();
animalArray[1] = new Cat();

Basically all subclasses of animal Class. When you want to retrieve the objects you can simply typecaset it

Dog dog = (Dog)animalArray[0];

To know the class you can simple use getClass() method. For example

    Animal[] animalArray = new Animal[10];
    animalArray[0] = new Dog();
    System.out.println(animalArray[0].getClass());

will print class Dog.

Agricola answered 19/7, 2013 at 3:57 Comment(1)
@Jason Yes that's correct. You could have just edited it :)Agricola
T
3

After OP's comment
THERE IS NO WAY TO GET ALL SUBTYPES OF A CLASS even using reflection.
But you can do it by another way , you can say which is the only but longest way.

  • Get a list of names of all classes that exist on the class path
  • Load each class and test to see if it is a subclass or implementor of the desired class or interface



Answer before OP's comment

As your question is not clear yet but I guess you want to use array or Collection which will store all of the instances even it is the instance of superclass or subclass.
Then I guess you need to do like this.

List<Object> list = new ArrayList<Object>();
         list.add(new Cat());
         list.add(new Dog());
         list.add(new Animal());
         list.add(new Cat());

         for (int i = 0; i < list.size(); i++) {

             if(list.get(i) instanceof Cat){
                 System.out.println("Cat at "+i);
             }else if(list.get(i) instanceof Dog){
                 System.out.println("Dog at "+i);
             }else if(list.get(i) instanceof Animal){
                 System.out.println("Animal at "+i);
             }
        }

This code is tested
Note: Keep in mind that Don't place parent class check like in case of example code (list.get(i) instanceof Animal) at top, otherwise it will pass both cases (if checks are only if-if-if) or skip one case(and always return the object as a Animal if checks are if-else if-else if) (list.get(i) instanceof Animal) and (list.get(i) instanceof Cat) If the returning object is a Cat object.

Truckle answered 19/7, 2013 at 3:32 Comment(1)
What I want is an array of object type, which I can use to instantiate objects of these types. If that is possible that is.Kwasi
S
1

As mentioned in another answer, this is not possible using purely reflection.

Unless you can customize your classes to specifically handle this case, you'd need to dive into either iterating over classes from the class loader, or using a custom class loader that adds the information into an internal data structure so that when it is requested later you don't have to reiterate over all classes.

Assuming you're not interested in diving into class loader code (it sounds like you are not), the next best way of doing this is adding static code to your classes that gets run at class loading time. For example:

public class Animal {
    protected static List subclasses = new ArrayList();
    //...
}

public class Cat extends Animal {
    static { 
        subclasses.add(Cat.class);
    }
    //...
}

This would be essentially what you would do with a custom class loader, where this code would live in the class loader instead of the class.

Repeat this pattern for all subclasses. Then when you want to create instances, you have class references inside the subclasses list, which you would instantiate with Class.newInstance (or another suitable reflection method if your constructors have arguments).

Spelter answered 11/12, 2013 at 0:47 Comment(0)
C
0

Since Java17, there is the concept of sealed classes, were we know all the available subclasses: Class.isSealed()

Class.getPermittedSubclasses()

https://www.baeldung.com/java-sealed-classes-interfaces

Cornela answered 7/5, 2024 at 14:13 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.