Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing a reference in Java

Tags:

java

android

I've this cards game, in which I store all the players in a List. To find out who's the player I want to act with, each player has a Card (I can get the card name), a name (I can get the player's name), but to be unique each player has an ID.

Now, at the beginning of my onCreate() method, I find, and assign a player of the list to a Player, Player clairvoyant:

public void initializeCharacters() {
    for (Player player : players) {
        if (player.getCardName().equals("Clairvoyant")) {
            clairvoyant = player;
        }
}

The game switch between Night and Day. The Clairvoyant's turn is during the night, and I used a switch to determine when's who's turn.

Now, before starting the Clairvoyant's turn, I check if he's alive or not, in negative case, I simply skip his turn:

case 2:
                    clairvoyant(); // Clairvoyant's turn
                    Toast.makeText(Game.this, String.valueOf(clairvoyant.getLifeStatus()), Toast.LENGTH_SHORT).show();
                    if(clairvoyant.getLifeStatus()) {
                    /* --- Let him choose ---*/
                        Intent intent = new Intent(this, ListPlayersClairvoyant.class);
                        Bundle bundle = new Bundle();
                        bundle.putSerializable("PLAYERS", (Serializable) players);
                        intent.putExtras(bundle);
                        startActivityForResult(intent, REQUEST_CLAIRVOYANT);
                    /* --------------------- */
                    }
                    nightInsideCounter++;
                    if(medium == null) {
                        nightInsideCounter++;
                    }
                    if(guard == null) {
                        nightInsideCounter++;
                    }
                    break;

And yet, I've added Toasts to see when I kill players if they're still alive, but even if the Player searched in the list is killed, the Clairvoyant player, previously created isn't.
So basically, the player in the list with the clairvoyant card, is dead; but the clairvoyant player, initialized before to have a reference to it before starting his turn, is still alive!

I don't understand why. Is anything I'm missing? Is that I've done a reference or not? In this case, how should I create a reference to it?


EDIT:

Now it all works fine, I have implemented the Parcelable interface on the Player Class and on the Card one too. The problem is when I get to the intent from ListPlayersVote Activity to the Game one (the main one), the App crashes and I get this error:

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference at android.widget.ArrayAdapter.createViewFromResource(ArrayAdapter.java:401)

[...] // Many other links, skipped

Which is a simple NullPointer exception, but I get no links to my code for the error, instead I get all other links to other scripts (Probably already made, not by me) and this keeps me stuck, how am I suppose to fix the bug if I don't get any link to my code?


Resources

Vote Activity

Player Class

How I retrieve the ArrayLists passed, and check for their values (this is a StartActivityForResult() ):

    /* ------------------------------------------ */
    /* ---------- If they want to VOTE ---------- */
    /* ------------------------------------------ */
    if(requestCode == REQUEST_VOTE) {

        if(resultCode == Activity.RESULT_OK) {
            // Get the Player clicked
            ArrayList<Player> highestList = data.getParcelableArrayListExtra("HIGHEST");
            ArrayList<Player> highestList1 = data.getParcelableArrayListExtra("HIGHEST1");
            System.out.println("[5] The players of the first list are " + highestList.size() + ".");
            System.out.println("[6] The players of the second list are " + highestList1.size() + ".");

            // Add the most voted players to a signle List, highest
                highest.addAll(highestList);
                highestList.clear();

                highest.addAll(highestList1);
                highestList1.clear();

            // Write the names in chat
            write("Il villaggio ha i propri sospettati:");
            for (Player player : highest){
                write(player.getName());
            }
            System.out.println("[7] The players chosen are " + highest.size() + ".");
            highest.clear();

        } else if (resultCode == Activity.RESULT_CANCELED) {
            // Some stuff that will happen if there's no result
        }

    }
like image 322
FET Avatar asked Jun 20 '16 14:06

FET


People also ask

Can you pass things by reference in Java?

Java is always Pass by Value and not pass by reference, we can prove it with a simple example.

How do you pass-by-reference?

Pass-by-reference means to pass the reference of an argument in the calling function to the corresponding formal parameter of the called function. The called function can modify the value of the argument by using its reference passed in. The following example shows how arguments are passed by reference.

Why pass-by-reference is not allowed in Java?

Java does not support call by reference because in call by reference we need to pass the address and address are stored in pointers n java does not support pointers and it is because pointers breaks the security. Java is always pass-by-value.

How do you pass by value and pass-by-reference in Java?

Java supports pass-by-value,0 but there are three different ways to create a pass-by-reference in Java. Make the member variable public inside a class. Return a value from a method and update the same inside the class. Create a single element array and pass it as a parameter to the method.

How do you pass a parameter in Java by reference?

Java Pass By Reference And Pass By Value There are basically two types of techniques for passing the parameters in Java. The first one is pass-by-value and the second one is pass-by-reference. One thing to remember here is that when a primitive typ e is passed to a method, then it is done by the use of pass-by-value.

Does Java pass objects by reference or value?

Answer: Java supports pass by value but when we are dealing with objects such as Java array objects, then the object reference is passed to the method. Q #3) Does Java pass objects by reference or value?

How to change the reference of a passed-in variable in Java?

Java always passes object references to method by value. That means passing the memory address of the object that the variable points to, not passing the variable itself, not the object itself. So we cannot change reference of a passed-in variable in a method. Other Recommended Tutorials:

What is pass by reference method in C++?

Pass By Reference: The pass by reference method passes the parameters as a reference (address) of the original variable. The called function does not create its own copy, rather, it refers to the original values only. Hence, the changes made in the called function will be reflected in the original parameter as well.


2 Answers

It seems you are in search of a weak reference: if no other reference to the object exists, the weak reference is lost too. See Reference too.

WeakReference<Player> clairvoyant;

// Initialisation of clairvoyant from players:
// So do this whenever players is filled.
for (Player player : players) {
    if (player.getCardName().equals("Clairvoyant")) {
        clairvoyant = new WeakReference<>(player);
    }
}

// Everywhere where clairvoyant is inspected:
Player player = clairvoyant.get();
if (player != null) {
    // There is a clairvoyant player:
    ,,,
}

No experience with Android's java behaviour though.

like image 110
Joop Eggen Avatar answered Oct 10 '22 18:10

Joop Eggen


The problem is when I get to the intent from ListPlayersVote Activity to the Game one (the main one), the App crashes and I get this error:

As I said in my comment, that exception related to the ArrayAdapter class happens when the adapter is used with a list of data that has null values in it. Looking through your code the culprit seems to be a Player object that doesn't have its fields initialized in the ListPlayersVote class. In that class, your current code will almost always introduce that non initialized Player object reference. In the ListPlayersVote's onCreate() callback you first add two Player objects to the holder lists, I'm assuming to have as a base for further calculations:

// remove the lines below , there's no need for them
// also simply doing new Player() will result in a Player which doesn't have    
// its fields initialized(and you don't update them later either)
highestList.add(new Player()); // is there a reason for adding this empty players?
highestList1.add(new Player());

Then in the onEntryClick() callback update your code to properly handle counting the players votes:

for (Player player1 : players){ // For each player
  // first of all you need to move the initialization for highest and highest1 INSIDE the
  // for loop to use the proper highest values at each iteration
  // With your current code the lists highestlist and highestlis1 each have
  // ONE Player object which is empty (because in the default constructor 
  // of Player you do nothing), you then use the empty initial Player in each list to
  // compare the vote count, this will mostly result in the first if  
  // clause(playerCount > highest) being triggered,
  // which will add the initial empty Player object to highestlist1
  int highest = highestList.size() == 0 ? -1 : highestList.get(0).getCount();// if the list is empty initialize it with -1 to signal the first player handled
  int highest1 = highestList1.size() == 0 ? -1 : highestList1.get(0).getCount();

  int playerCount = player1.getCount(); // Get his votes

    // you need to check for -1 to handle the case when you're dealing 
    // with the first player( which of course will have the highest 
    // count as there's no either player to compare it yet)
    if(playerCount > highest || highest == -1){ // If they're the highest so far, add it to the 1st list
        highestList1.addAll(highestList);
        highestList.clear();
        highestList.add(player1);
        // the same for highest1
    } else if (playerCount > highest1 || highest1 == -1){ // If they're the 2nd highest so far, add it to the 2nd list
        highestList1.clear();
        highestList1.add(player1);
    }else if(playerCount == highest){ // If they're equal to the current highest one, add it to the 1st list as well
        highestList1.add(player1);
    } else if (playerCount == highest1){ // If they're equal to the current 2nd highest one, add it to the 2nd list as well
        highestList1.add(player1);
    }
like image 1
user Avatar answered Oct 10 '22 20:10

user