Call an object from a map and cast directly

Viewed 111
private static final Map<Integer, GameObject> OBJECT = new ConcurrentHashMap<>();

I have a map in which I store GameObjects, which is extended by PlayerObject, NpcObject, ItemObject.

I'm trying to create a method on which I call the object by ID and class type and cast at it directly and if it's not exists or the class of the object ID does not match the given one to return null. So for example

final PlayerObject object = getObject(<id>, PlayerObject);

Is there any way?

Edit:

I managed to do this:

public <T extends EventObject> T getObject(final int objectId)
    {
        final EventObject object = OBJECT.get(objectId);

        return Objects.nonNull(object) && object.getClass() ==  ? T (object) : null;
    }

But i don't want to use Class<? extends EventObject> in parameter of this method. Can't i somehow check using the generic T if it's the same class to cast it and return or else null?

4 Answers

You can use Class#isInstance to check if the object's type is correct and Class#cast to convert the object to the correct type.

public static <T extends GameObject> T getObject(Integer id, Class<T> clazz) {
    GameObject obj = OBJECT.get(id);
    if(!clazz.isInstance(obj)) return null;
    return clazz.cast(obj);
}
// ...
final PlayerObject object = getObject(<id>, PlayerObject.class);

try this complete generic method:

public static <T> T getObject(int id,  Class<T> c){
    Object object = OBJECT.get(id);
    return object != null && object.getClass() == c ? c.cast(object) : null;
}

The other parts of the program:

private static final Map<Integer, GameObject> OBJECT = new ConcurrentHashMap<>();

public static void main(String[] args) throws ParseException {
    init();
    PlayerObject p = getObject(3, PlayerObject.class);
    ItemObject i = getObject(3, ItemObject.class);
    PlayerObject p2 = getObject(4, PlayerObject.class);
    System.out.println(p);
    System.out.println(i);
    System.out.println(p2);
}

private static void init() {
    OBJECT.put(1, new PlayerObject(1, "SomePlayer1"));
    OBJECT.put(2, new PlayerObject(2, "SomePlayer2"));
    OBJECT.put(3, new ItemObject(3, 5));
    OBJECT.put(4, new ItemObject(4, 7));
}

GameObject.class

public class GameObject {

    protected int id;

    GameObject(int id) {
        this.id = id;
    }

    public int getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }

}

PlayerObject.class

public class PlayerObject extends GameObject {

    private String playerName;

    PlayerObject(int id, String playerName) {
        super(id);
        this.playerName = playerName;
    }

    public String getPlayerName() {
        return this.playerName;
    }

    public void setPlayerName(String playerName) {
        this.playerName = playerName;
    }

    @Override
    public String toString() {
        return "PlayerObject{\"id\": " +
                this.id +
                ", \"playerName\": \"" +
                this.playerName +
                "\"}";
    }

}

ItemObject.class

public class ItemObject extends GameObject {

    private int itemCount;

    ItemObject(int id, int itemCount) {
        super(id);
        this.itemCount = itemCount;
    }

    public int getItemCount() {
        return this.itemCount;
    }

    public void setItemCount(int itemCount) {
        this.itemCount = itemCount;
    }

    @Override
    public String toString() {
        return "ItemObject{\"id\": " +
                this.id +
                ", \"itemCount\": " +
                this.itemCount +
                "}";
    }

}

And the output of the program:

PlayerObject{"id": 1, "playerName": "SomePlayer1"}
ItemObject{"id": 3, "itemCount": 5}
null
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

public class Stackoverflow_68734414 {
    private static Map<Integer, GameObject> OBJECT_MAP = new ConcurrentHashMap<>();
    public static void main(String[] args) {

        PlayerObject po = new PlayerObject();
        ItemObject io = new ItemObject();

        OBJECT_MAP.put(1, po);
        OBJECT_MAP.put(2, io);

        PlayerObject p1 = getObject(1, PlayerObject.class);
        PlayerObject p2 = getObject(2, PlayerObject.class);
        ItemObject i1 = getObject(1, ItemObject.class);
        ItemObject i2 = getObject(2, ItemObject.class);

        System.out.println(p1);
        System.out.println(p2);
        System.out.println(i1);
        System.out.println(i2);

    }

    public static <T extends GameObject> T getObject(Integer id,  Class<T> klass){
        GameObject object = OBJECT_MAP.get(id);
        if(Objects.nonNull(object) && (object.getClass() ==  klass)) {
            return klass.cast(object);
        } else{
            return null;
        }
    }

}

class GameObject{

}

class PlayerObject extends GameObject {

}

class ItemObject extends GameObject{

}

Output is as expected:

PlayerObject@179d3b25
null
null
ItemObject@254989ff

Are you looking for something similar to this:

public boolean isItemObject(int id){

   GameObject obj = OBJECT.get(id)
   
   if(obj instanceof ItemObject && obj != null){
     
      return true;
   }

   return false;

}

public boolean isPlayerObject(int id){

   GameObject obj = OBJECT.get(id)
   
   if(obj instanceof PlayerObject && obj != null){
     
      return true;
   }

   return false;

}

public boolean isNPCObject(int id){

   GameObject obj = OBJECT.get(id)
   
   if(obj instanceof NpcObject && obj != null){
     
      return true;
   }

   return false;

}

//...

final PlayerObject pObject = isPlayerObject(objectID) ? OBJECT.get(id) : null;
Related