3

I have an array of game objects in the GameWorld and they can get removed from that world. The problem is that some game objects have references to other game objects. E.g. Player class has a reference to a Bird. Bird gets randomly removed from GameWorld, but Player still has a reference to it. I currently do a null check to check whether the GameObject is still valid and in the world. However, removing an object from the array does not make that reference null. So how can I make it null?

Here is an example:

// GameWorld creates bird
ArrayList<Object> gameObjects = new ArrayList<>();
Object bird = new Object();
gameObjects.add(bird);

// Player references it
Object referencedBird = gameObjects.get(0);

// later in GameWorld, another scope, there is no access to the 'bird' object, trying to remove the bird from the world
Object objectToRemove = gameObjects.get(0);
gameObjects.remove(0);
objectToRemove = null;

// back in the Player class
Debug.log("is null " + (referencedBird == null)); // false! I need it to be true
1
  • You might want to look at java's WeakReference Commented Jul 25, 2016 at 14:32

4 Answers 4

6

You can't make an object null, you can only make a reference null. Updating one reference to an object doesn't change other references to the same object.

Think about it like us both having the same person's number in our phones: if I delete the number, it doesn't get deleted from your phone. And if we both delete it, that person's phone number doesn't cease to exist: just neither of us can call them.

The only things you can do are:

  • Set referencedBird = null explicitly;
  • Or refer to it via gameObjects.get(0) instead of via the referencedBird variable.
Sign up to request clarification or add additional context in comments.

8 Comments

But when there are lots of objects, looping through the whole array and searching for the right object seems inefficient, isn't there a better way?
You don't need to search if you have the object's index (assuming that they are stored in a List which implements RandomAccess, like ArrayList); or, you could use a Map<SomeKeyType, Object> if you don't necessarily want to have to keep all of the "empty" spaces in the list when you null-out an element.
GameObjects get added and removed quite often, so indices are always shifting, so keeping it wouldn't work
You can use the ArrayList to check if it contains referencedBird in the player...instead of checking if referencedBird is null
@boxed__l a HashSet internally uses a HashMap, where the map keys are the values in the set and the map values are arbitrary. But no, I am suggesting a trivially-constructable key (e.g. a String or Integer).
|
1

Okay since Andy pointed out that you can not destroy a object itself you can still have a work-around.

 interface RemoveAble<T>{
        boolean isRemoved();
        T prepareRemoveAndGet();
    }

class Bird implements RemoveAble<Bird>{
    boolean shouldRemove = false;
    @Override
    public boolean isRemoved() {
        return shouldRemove;
    }

    @Override
    public Bird prepareRemoveAndGet() {
        shouldRemove = true;
        return this;
    }
}

And use it like this:

// GameWorld creates bird
ArrayList<RemoveAble> gameObjects = new ArrayList<>();
Bird bird = new Bird();
gameObjects.add(bird);

// Player references it
Bird referencedBird = gameObjects.get(0);

// later in GameWorld, another scope, there is no access to the 'bird' object, trying to remove the bird from the world
Object objectToRemove = gameObjects.get(0).prepareRemoveAndGet;


// back in the Player class
Debug.log("is null " + (referencedBird.isRemoved == true)); // false! I need it to be true

And then null it by yourself e.g.

if(referencedBird.isRemoved) referencedBird = null;

1 Comment

@Gintas_ See if its useful for you.
0

First you need to better understand how Java variables work:
I you set a variable to null that does not affect the object behind it at all. You would need to somehow invalidate the referenced object (using a boolean variable) or the better solution would be to always get the object directly from the ArrayList.

Comments

0

Unlike C and C++ in java you cant manipulate memory directly, the only option you have is to remove all the Strong (regular) reference to obj and leave to JVM to remove it from memory whenever it needs memory.

    // GameWorld creates bird
    ArrayList<Object> gameObjects = new ArrayList<>();
    Object bird = new Object();
    gameObjects.add(bird);

    // a weak reference to array Item
    WeakReference<Object> referencedBird = new    WeakReference(gameObjects.get(0));
    // manipulating and accessing array item via weak reference
    referencedBird.get().toString();

    // after this remove there is no strong reference to array element (0) and it is available for JVM to revoke
    //memory allocated to it in up-coming garbage collection cycle
    gameObjects.remove(0);

    //garbage collection may remove the obj from memory so this method may return null
    referencedBird.get();

Also you have the option to make your gameObjects list, memory efficient by making array of type WeakReference

     ArrayList<WeakReference> weakReferenceToGameObjects = new ArrayList<>();
    Object bird1 = new Object();
    weakReferenceToGameObjects.add((WeakReference) bird1);

    bird1 = null;

    // now if you try to get the element you may get null!
    weakReferenceToGameObjects.get(0).get();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.