reflection, create a specific object given an int - java

I have classes like Dog.java,Cat.java,Bird.java,Fish.java,Not_Listed.java etc. I also have a ID.java which only keeps some final int mapping:
public class ID{
public static final int CAT = 1;
public static final int DOG = 3; // there maybe some integers skipped
public static final int FISH = 4; // but all integers are unique
public static final int BIRD = 6;
public static final int NOT_LISTED = -1;
}
All classes listed above extends Animal.java class.
What I need is given "6" I need to create a Bird object, given "1" I need to create Cat object. Given "2" or "5" I can return a Not_Listed object or simply throw an error(both works). I could simply do it with a switch case or HashMap but my list is somehow long and I dont want to update the code whenever my list grows. So I came up with reflection, but I have no idea how to do it?
Any other efficient solutions are also welcome. Sorry for being noob about reflection. Thanks in advance.
edit: IDs are must

You don't need reflection for this.
Create an enum instead of your id class and have a class reference inside the enum, i.e.:
enum Animal {
CAT(1, Cat.class),
DOG(2, Dog.class),
FISH(3, Fish.class);
private final Class clazz;
private final int id;
Animal(int id, Class clazz) {
this.id = id;
this.clazz = clazz;
}
public Object generateInstance() {
return clazz.generateInstance();
}
public class getGeneratedClass() {
return clazz;
}
public int getId() {
return id;
}
}
This makes use of the feature of Java that allows enums to be fully featured classes and it records the Class to use within each entry in the enum. You can then use that Class to generate new instances on demand so long as the class has a 0-argument constructor.
To use this just do:
Animal.DOG.generateInstance() // Returns a Dog object
Animal.CAT.generateInstance() // Returns a Cat object
If you wanted to be able to get a type from id you could either build a HashMap inside the enum to do the lookup or just loop over the enum.values() looking for a match.

A completely different approach so I'm doing it as a separate answer.
Just create a Map from id to class:
public static final int CAT = 1;
public static final int DOG = 3; // there maybe some integers skipped
public static final int FISH = 4; // but all integers are unique
public static final int BIRD = 6;
public static final int NOT_LISTED = -1;
Map<Integer, Class> classMap = new HashMap<>();
classMap.put(CAT, Cat.class);
classMap.put(DOG, Dog.class);
classMap.put(FISH, Fish.class);
public Object generateInstance(int id) {
// Will throw NullPointerException if id isnt in map, you might want to consider some checks
return classMap.get(id).generateInstance();
}
That will do what you want, you really should look at the enum design I posted in the other answer though - it will give much better results in the long term.

This has Factory design pattern written all over it. You can register each Animal class (e.g. Cat, Fish, Dog, Bird, etc.) in their respective classes.
See Class Registration - avoiding reflection on http://www.oodesign.com/factory-pattern.html
You can have an AnimalFactory that keeps a map of ID to class that implements Facotry Method. Then you would register it in each specific implementation of Animal. This way AnimalFactory wouldn't need to change, just each new Animal that is added would need to register the specific factory:
public class Dog extends Animal
{
...
static
{
AnimalFactory.instance().registerAnimal(ID.DOG, new DogCreator());
}
...
}
public class DogCreator extends AnimalFactory
{
//Abstract factory method in AnimalFactory that gets called to return the Animal
public Animal createAnimal
{
return new Dog();
}
}
Begin Edit
You can also have a generic Animal creator that uses reflection to make the new class (assuming each Animal has an empty constructor). This would still require you to register your specific id in each Animal implementation:
public class Dog extends Animal
{
...
static
{
AnimalFactory.instance().registerAnimal(ID.DOG, Dog.class);
}
...
}
Then AnimalFactory can use reflection to make the instance:
public Animal createAnimal(ID id)
{
return animalMap.get(id).newInstance();
}

Related

Required class variables in Java?

So say, for the purposes of illustration that I have an abstract class Animal, and every Animal has a numberOfLegs.
Dog extends Animal and all dogs have a numberOfLegs of 4.
Is it possible to make numberOfLegs...
Static
Required (everything that extends Animal has to define numberOfLegs, or there is some default value)
Accessible from Animal (this one I'm not as concerned about, but if say the method walk() was called from Dog, could Animal view the number of legs without having to pass an extra value?)
Sorry if this is a strange question, and yes, I understand that I could do this easily in other ways, such as making it an instance variable instead of static, but I'm just kind of curious if there's a better way.
Neither static variables or instance variables participate in polymorphism. Just declare an abstract method, e.g. int getNumberOfLegs(), in the abstract class. Your Dog class could be:
class Dog extends Animal {
private static final int NUMBER_OF_LEGS = 4;
public int getNumberOfLegs () {
return NUMBER_OF_LEGS;
}
}
Is it possible to make numberOfLegs: Static
This would make every instance of a class that extends Animal have the same numberOfLegs. See: here for an explanation.
public abstract class Animal
{
private static int NUMBER_OF_LEGS = 4;
}
Is it possible to make numberOfLegs: Required
Yes, you just have to make a property in the abstract class and initialise it in the constructor.
public abstract class Animal
{
private int numberOfLegs;
public int getNumberOfLegs()
{
return this.numberOfLegs;
}
public Animal(int numberOfLegs)
{
this.numberOfLegs = numberOfLegs;
}
}
public class Zebra extends Animal
{
public Animal(int numberOfLegs)
{
super(numberOfLegs);
}
}
everything that extends Animal has to define numberOfLegs, or there is some default value
Furthermore, if you wanted a default value for number of legs, you could inlcude a constructor for Animal without a numberOfLegs parameter and set it to a value, say 4.
public abstract class Animal
{
private int numberOfLegs;
public Animal()
{
this.numberOfLegs = 4;
}
}
Is it possible to make numberOfLegs: Accessible from Animal
Yes, you can call the method (if it's abstract in the Animal class) from any object that extends Animal
Zebra z = new Zebra(4);
System.out.println(z.getNumberOfLegs());

Sorting an Array created with Inheritance by a type in child class Java

I have created an array of animals that contains objects of a type "Vertebrates", which is made from a number of classes that extends "Vertebrates".
Essentially there a number of animal classes (ex. "Dog", "Human", etc.) that extend a "Mammals" class, which extends the "Vertebrates" class
I need use Selection sort on this array by the names given for each of these animals.
I have been trying to do this using Comparable and modifying the compareTo() and then use Arrays.sort(Vertebrates[] list)
I keep getting the following exceptions
java.util.Arrays.mergeSort(Arrays.java:1144)
at java.util.Arrays.sort(Arrays.java:1079)
at project3.AnimalDatabase.main(AnimalDatabase.java:188)
I am not sure I am implementing the Comparable or the toCompare() part correctly. I have been looking at other Q/A's but have not found a definitive answer
//Driver class for program
public class AnimalDatabase {
public static void sort(Vertebrates[] list)
{
}
main{
//this creates a list called "animalList" of type Vertebrates
//the method in which the array is initialized and populated has been omitted here to save space.
//the list will contain a number of different animal types "Dog" "Human", etc.
Vertebrates[] animalList = new Vertebrates[10];
}
Arrays.sort(animalList);
for(int i=0; i<animalList.length; i++)
{
System.out.println("sorted list is " + animalList[i]);
}
//Verebrates class
//some getters and setters have been omitted, as well as a toString() method
public abstract class Vertebrates implements Comparable<Vertebrates>
{
static int count=0;
int id;
int brainSize;
int lengthOfVertebralColumn;
Vertebrates(int brainSize, int lengthOfVertebralColumn)
{
id=count;
this.brainSize=brainSize;
this.lengthOfVertebralColumn=lengthOfVertebralColumn;
count++;
}
public String compareTo(Vertebrates other)
{
String otherFirst = ((Mammals)other).getName();
return otherFirst;
}
}
//Mammals class
//some getters and setters have been omitted, as well as a toString() method
public class Mammals extends Vertebrates implements Comparable<Vertebrates>
int NumberOfTeeth;
int NumberOfFeet;
String Name;
Mammals(int brainSize, int lengthOfVertebralColumn, int NumberOfTeeth,int NumberOfFeet, String Name)
{
super(brainSize, lengthOfVertebralColumn);
this.NumberOfTeeth=NumberOfTeeth;
this.NumberOfFeet=NumberOfFeet;
this.Name=Name;
}
public String getName() {
return Name;
}
//example of one of the animal classes
//some getters and setters have been omitted, as well as a toString() method
public class Dog extends Mammals implements Comparable<Vertebrates> {
Dog(int brainSize, int lengthOfVertebralColumn, int NumberOfTeeth, int NumberOfFeet, String Name, boolean domestic, CoatTypes TypeOfCoat)
{
super(brainSize, lengthOfVertebralColumn, NumberOfTeeth, NumberOfFeet, Name);
this.domestic=domestic;
this.TypeOfCoat=TypeOfCoat;
}
If you are defining the compare logic in super class Vertebrates then you can use properties of super class only that is defined for all sub-classes otherwise how you will compare the objects of different sub-classes in an array.
Super-class doesn't know about its sub-classes so don't use any sub-class in super-class method.
How will you compare Mammals with Animals?

Creating an EnumMap with a generic type Enum

If I have a bunch of classes that all contain an Enum and EnumMap and I want to create a superclass for those classes.
public interface ColorEnum {
}
class ColorMarbles extends Toy {
enum MARBLE implements ColorEnum
{ BLUE, GREEN }
EnumMap<MARBLE, String> names = new EnumMap<MARBLE, String>(MARBLE.class);
//stuff
// fields
public void populate(ArrayList<String> designer) {
int i = 0;
for(MARBLE marble : MARBLE.values()) {
marble.name = designer.get(i);
i++;
}
}
}
class ColorBalloons extends Toy {
enum BALLOON implements ColorEnum
{ YELLOW, RED }
EnumMap<BALLOON, String> names = new EnumMap<BALLOON, String>(BALLOON.class);
//stuff
// fields
public void populate(ArrayList<String> designer) {
int i = 0;
for(BALLOON balloon : BALLOON.values()) {
balloon.name = designer.get(i);
i++;
}
}
}
How do I make create a superclass to have a generic EnumMap that contains an enum of type ColorEnum like this?
public abstract class Toy {
EnumMap<ColorEnum, String> names;
}
eidt: I realize that I was too vague with my example. Dogs are probably a bad example. I change it to something hopefully more clear.
What I have is a bunch of classes with methods like populate which populates the EnumMap. The names are in a predefined order. Instead of defining populate in every class, I'm hoping to be able to bring it to the Toy superclass so I don't have to keep copy-pasting in each new class type Toy.
Hopefully this will explain more what I'm looking for.
I have a feeling your design is needlessly overcomplicated.
With enums
If you don't require a class inheritance, you can work with enums directly as with top level classes.
public interface Animal {}
public enum Dog implements Animal {
HUSKY("Husky"), LAB("Labrador");
private final String name;
Dog(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Enums can declare fields, methods and implement interfaces like any other Java classes. Their only limitation is that their direct superclass is always java.lang.Enum and they can't be extended.
However every enum constant can have its own set of unique data passed to its constructor. It is even possible that each of the constants can override a common method of that enum with its unique implementation.
A nice tutorial explaining more about the full power of enums:
http://javarevisited.blogspot.cz/2011/08/enum-in-java-example-tutorial.html
Without enums
In case you need an actual class inheritance for sharing some common methods (for example from the Animal superclass), I still would drop the map approach and rather try something more OOP oriented:
public class Animal {
}
public abstract class Dog extends Animal {
public abstract String getName();
public static class Husky extends Dog {
#Override
public String getName() {
return "husky";
}
}
public static class Lab extends Dog {
#Override
public String getName() {
return "labrador";
}
}
}
One mechanism I have used for something like this is to extend a generic base class that has a generic parameter that allows you to pass the Enum details up to it.
This example defines a base Table class for database tables:
public class Table<Column extends Enum<? extends Column>> {
// Name of the table.
protected final String tableName;
// All of the columns in the table. This is actually an EnumSet so very efficient.
protected final Set<Column> columns;
/**
* The base interface for all Column enums.
*/
public interface Columns {
// What type does it have in the database?
public Type getType();
}
// Small list of database types.
public enum Type {
String, Number, Date;
}
public Table(String tableName,
Set<Column> columns) {
this.tableName = tableName;
this.columns = columns;
}
}
Now you can subclass this:
public class VersionTable extends Table<VersionTable.Column> {
public enum Column implements Table.Columns {
Version(Table.Type.String),
ReleaseDate(Table.Type.Date);
// Sadly all of this must be in ALL of your enums but most of the work can be pushed up to `Table`
final Table.Type type;
Column(Table.Type type) {
this.type = type;
}
#Override
public Type getType() {
return type;
}
}
public VersionTable() {
super("Versions", EnumSet.allOf(Column.class));
}
}
and make use of functionality in the parent class that handles your enum.
Note here I am passing an EnumSet to the Table constructor. I am sure you could change this to accommodate your EnumMap requirement if you decide an EnumSet is insufficient.

Generic <T extends A> class uses A static field instead of T's one

Here's my situation
public abstract class Actions {
public static Actions STAND;
public static Actions ATTACK;
public static Actions COLONIZE;
public static Actions DEFEND;
public static Actions TURN_CW;
public static Actions TURN_CCW;
public static Actions DIE;
public abstract long[] getFramesDurations();
public abstract int[] getBaseTiles();
}
public class SimpleActions extends Actions{
public static Actions STAND = new SimpleActions( new long[]{120,120,120,120,120,120,120}, new int[]{0,1,2,3,4,5,6});
public static Actions ATTACK = new SimpleActions( new long[]{120,120,120,120,120,120,120,120,120}, new int[]{7,8,9,10,11,12,13,14,15});
public static Actions COLONIZE = new SimpleActions( new long[]{120,120,120,120,120,120,120}, new int[]{7,8,9,10,11,12,13,14,15});
public static Actions DEFEND = new SimpleActions(new long[]{1}, new int[]{1});
public static Actions TURN_CW = new SimpleActions( new long[]{1}, new int[]{1});
public static Actions TURN_CCW = new SimpleActions( new long[]{1}, new int[]{1});
public static Actions DIE = new SimpleActions( new long[]{1}, new int[]{1});
private final long[] mActionFramesDurations;
private final int[] mActionBaseTiles;
SimpleActions(long[] pActionFramesDurations, int[] pActionBaseTiles) {
mActionFramesDurations = pActionFramesDurations;
mActionBaseTiles = pActionBaseTiles;
}
public long[] getFramesDurations()
{
return mActionFramesDurations;
}
public int[] getBaseTiles()
{
return mActionBaseTiles;
}
}
public abstract class A<T extends Actions> {
A() {
doSomething(T.STAND);
}
protected void doSomething(Actions action) { use action somewhere}
}
public class B extends A<SimpleActions> {
B() {
super();
}
}
I always get nullPointerException when the constructor of A calls doSomething because action is null..
Since B extends A i was expecting it to use SimpleActions.STAND, and not Actions.STAND.
What am i doing wrong? How should i do this?
The type parameters to a generic are not known at run time. In other words, at run time, there's no difference between an A<Actions> and an A<SimpleActions>. The jvm therefore can't tell that you want SimpleActions.STAND, rather than Actions.STAND. If you need the type parameters to be known at run time, you'll need to carry them around in a separate variable.
Read up on "run time type erasure" if this isn't clear.
Edited following your comment -
If you're only doing this logic in the constructor, you could make the constructor look like
A( Class<? extends Action> actionType ){
if( SimpleActions.class.isAssignableFrom( actionType )){
doSomething( SimpleActions.STAND );
}
else{
doSomething( Actions.STAND );
}
}
If you need the same logic outside of the constructor, then make a member variable of type Class<? extends Action> inside A to store the actionType.
The Java Language Specification writes:
The members of a type variable X with bound T & I1 ... In are the members of the intersection type (ยง4.9) T & I1 ... In appearing at the point where the type variable is declared.
That's why the expression T.STAND refers to Actions.STAND, not SimpleActions.STAND.
Actions.STAND and SimpleActions.STAND are different fields (unlike non-static methods, fields can not be overriden.)
That already highlights one way to delegate to the subclass: Define an accessor method (a getter) that subclass must override:
abstract class Actions {
abstract Actions stand();
}
class SimpleActions extends Actions {
private static final Actions STAND = ...;
#Override Actions stand() { return STAND;}
}
and invoke
t.stand();
where t is an instance of T provided to A upon construction. Or perhaps move this method into a different type (MotionRegistry?) and provide an instance of that upon construction of A.
That said, your design appears pretty complicated, I can't shake the feeling that your code could be simplified (do you need the distinction between Actions and SimpleActions if both describe the same actions?)

How can I force subclasses to redefine a constant in Java?

How can I have a generic abstract class, let's say Animal, and have it implement a constant (or a variable; it doesn't mind) which must be redefined by all subclasses?
Example:
abstract class Animal {
private static int venerableAge;
}
And force Dog to be defined something like
class Dog extends Animal {
private static int venerableAge = 10;
}
I don't want different subclasses to be able to read nor write each others' value. Just the one of themselves.
I.e., each class must have its own static "instance" of the variable. And no one will access the parent's.
Is that possible in Java?
The trick is to do this with getter methods rather than directly with fields:
abstract class Animal {
abstract int getVenerableAge();
}
class Dog extends Animal {
private static int venerableAge = 10;
public int getVenerableAge() {
return venerableAge;
}
}
EDIT:
How about letting the constructor do the contract binding:
abstract class Animal {
public Animal(int venerableAge){
//carry out sense checks here. i.e.:
if (venerableAge < 0) { /* doSomething */ }
}
}
class Dog extends Animal {
private static int venerableAge;
public Dog(int age) {
super(age)
venerableAge = age;
}
}
Now Dog and Cat are both forced to be created with venerable ages, but (as implemented above) can't see each others value.

Categories

Resources