Copying an Object from Array to Array in Java - java

I'm trying to copy an Object I've created from one array to another of the same type in Java. When I run my program I receive a NullPointerException.
The relevant class functions are:
private int mState;
public Cell(int pRow, int pColumn, int pState) {
//other things
setState(pState);
}
public void setState(int pNewState) {
mState = pNewState;
}
public void setDead() {
mState = DEAD;
}
and the line in which the error occurs:
mFutureGeneration[i][j].setDead();
That array is defined as
private Cell [][] mFutureGeneration;
then dimensioned as
mFutureGeneration = new Cell[100][100];
It receives its contents from:
Cell [][] vSeedArray = new Cell[100][100];
which is filled as
for (int i = 0; i<100; i++) {
for (int j = 0; j<100; j++) {
int vNewState = mGenerator.nextInt(2) - 1;
vSeedArray[i][j] = new Cell(i,j,vNewState);
}
}
I think the problem is happening in the copy, but I was always under the impression Java copied by reference, so I can't see why it would be failing.
I copy the contents across with a loop
for(int i = 0; i<vSeedArray.length; i++) {
for(int j=0; j<vSeedArray[i].length; j++) {
mCurrentGeneration[i][j] = vSeedArray[i][j];
}
}
Any help would be appreciated.
Thanks.

I'm not sure you're ever allocating any "Cell" objects - just the array to hold them.
If so, that's probably the cause of your NullPointer exception.
Good link:
http://www.willamette.edu/~gorr/classes/cs231/lectures/chapter9/arrays2d.htm
Scroll down to the section "Array of Objects".
'Hope that helps!

Related

How to modify array without its modification in previously added deque?

I faced the next problem.
The simplified view of my code is:
class Board{
Cell[][] cells = new Cell[9][9]
Deque<Cell[][]> cellsReserved = new ArrayDeque<>();
public static void main(){
cells[5][4] = new Cell(5);
cellsReserved.add(cells);
cells[5][4].setValue(10);
cellsReserved.add(cells);
while(!cellsReserved.isEmpty()){
System.out.println(cellsReserved.poll()[5][4].getValue());
}
}
}
class Cell{
private int value;
public Cell(int value){
this.value = value;
}
public void setValue(int value){
this.value = value;
}
public int getValue() {
return value;
}
}
I want to get next result:
5
10
But the result is
10
10
I researched this issue and found that the core problem is that collections in Java save not values but references so modifying objects after setting its to collections causes their modification in collections.
I found the solution for adding lists to deque:
deque.addLast(list.stream().toList())
or
deque.addLast(new ArrayList<>(list));
But such approach doesn't work with arrays because
cellsReserved.add(Arrays.stream(cells).toArray(Cell[][]::new))
doesn't solve problem and value in deque is modified after modification of value of Cell not in deque.
I would be grateful if you help me with this problem.
There is only a single instance of Cell[][] cells here, so no matter how many times it is added to the Deque it is still the same reference to same instance. Moreover cells[5][4].setValue(10); overrides the value inside the selected Cell instance, so you need to create a new Cell each time.
It is not very clear from the question what is the overall purpose of this code. If the goal is to have a "history" per board cell, consider using an array of Deques instead. Since arrays of generics are not directly supported (possible with Array.newInstance() but won't get into this now), the array-of-arrays can be replaced by a flat ArrayList, but you will have to calculate the coordinates explicitly.
It can be something like this:
List<Deque<Cell>> cellsReserved = new ArrayList<>(9 * 9);
for (int i = 0; i < 9 * 9; i++) {
cellsReserved.add(new ArrayDeque<>());
}
Deque<Cell> dequeOf5_4 = cellsReserved.get(5 + 4 * 9);
dequeOf5_4.add(new Cell(5));
dequeOf5_4.add(new Cell(10));
while(!dequeOf5_4.isEmpty()){
System.out.println(dequeOf5_4.poll().getValue());
}
Update following #Ensei's comment:
For the case you need snapshot of the entire array/matrix in each Deque element, you can deep copy the matrix before each change. This may look like this:
public static void main(String[] args){
Deque<Cell[][]> cellsReserved = new ArrayDeque<>();
Cell[][] cells = new Cell[9][9];
cells[5][4] = new Cell(5);
cellsReserved.add(cells);
cells = deepCopy(cells);
cells[5][4].setValue(10);
cellsReserved.add(cells);
while(!cellsReserved.isEmpty()){
System.out.println(cellsReserved.poll()[5][4].getValue());
}
}
private static Cell[][] deepCopy(Cell[][] cells) {
Cell[][] copy = new Cell[cells.length][cells[0].length];
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[i].length; j++) {
Cell source = cells[i][j];
if (source != null) {
copy[i][j] = new Cell(source.getValue());
}
}
}
return copy;
}
Note that the deep copy method creates a new instance of the array and a new instance of each Cell object.

JUnit: test builder with private field

I'm a beginner and I have a problem with JUnit test in the constructor of a class.
The class that I want to test is called IntSortedArray and is as follows:
public class IntSortedArray {
private int[] elements;
private int size;
public IntSortedArray() {
this.elements = new int[16];
this.size = 0;
}
public IntSortedArray(int initialCapacity) throws IllegalArgumentException {
if(initialCapacity < 0) {
throw new IllegalArgumentException("Error - You can't create an array of negative length.");
}
else {
elements = new int[initialCapacity];
size = 0;
}
}
public IntSortedArray(int[] a) {
elements = new int[a.length + 16];
for(int i = 0; i < a.length; i++)
elements[i] = a[i];
size = a.length;
insertionSort(elements);
}
//other code...
}
With Eclipse I created a class for JUnit:
public class IntSortedArrayUnitTest {
private IntSortedArray isa;
#Test
public void testConstructorArray16Elements() {
isa = new IntSortedArray();
int expected = 0;
for(int i: isa.elements) **<-- ERROR**
expected += 1;
assertEquals(expected, 16);
}
}
I started to write a test class with the intention to test all the methods of the class IntSortedArray, including constructors.
The first method testConstructorArray16Elements() wants to test the first builder.
So I thought I would check if the creation of the array elements is done properly, so the for loop counts how long elements and make sure it along 16 (as required).
But Eclipse generates (rightly) a mistake because elements is private.
How can I fix this error? I don't want to put the public field and if possible I would like to avoid creating a method public int[] getElements().
What do you recommend?
Another question: I can do two assert the same method? One to test the length of the array and the other to test that size is 0.
I hope not to have made big mistakes, this is the first time I use JUnit.
PS: how can I test the second constructor?
Thank you very much!
It looks like your class fields are declare as private but you trying to access then from outside the class. You need to provide the accessors methods in you class to make them visible:
private int[] elements;
private int size;
public static final int MAX = 16;
public int[] getElements() { ... }
public int getSize() { return size; }
Then you will be able to write below code:
isa = new IntSortedArray();
int expected = 0;
for(int i: isa.getElements()) {
expected += 1;
}
assertEquals(expected, IntSortedArray.MAX );
It looks like your constructor has created an array for 16 integers, but does not initialize it with any value. To do that you should have below code:
public IntSortedArray() {
this.elements = new int[MAX];
this.size = 0;
for (int i=0 ; i < MAX ;i++) {
elements[i] = i;
size++;
}
}
You'll have to write a getter method for your array, or implement an Iterator

java.lang.NullPointerException when passing a boolean through an array

I'm trying to make a game for my Java class, but I keep getting a NPE. I know that it means one of the variables being passed is a null, but I have no idea where. I have checked all variables involved. I believe it may be an issue with initializing the arrays, but I'm still not seeing what I've done wrong. I've checked around stack overflow and I have seen NPEs due to various reasons, but I can't find a solution that works on mine.
public class Inventory{
public int gold = 0;
private Item[] itemListArray = new Item[30];
private JButton[] itemButtonArray = new JButton[30];
private JButton buttonBack = new JButton("Back");
private static final String HOME = "Home";
public Inventory() {
for(int i = 1;i < 31; i++)
{
itemListArray[i].emptySlot = true; //Here is where the NPE hits
}
}}
That is where the NPE calls for the error
public class Item {
protected String name = "";
protected int def = 0;
protected int stack = 100;
protected boolean stackable = false;
protected boolean consume = false;
boolean emptySlot = true;
protected ImageIcon icon;
public Item(){
}
public boolean isArmor()
{
if(def >= 1)
{
return true;
} else {
return false;
}
}
public boolean isConsumable()
{
if(consume = true)
{
return true;
} else {
return false;
}
}
public boolean isEmpty()
{
if(emptySlot = true)
{
return true;
} else {
return false;
}
}
Here is the declaration of Item.
Please Answer soon to my issue, I can't seem to figure it out.
Item[] itemListArray = new Item[30];
This code just creates an array that contains null values, you need to initializes each individual value in the array.
for(int i = 1;i < 31; i++)
{
itemListArray[i].emptySlot = true; //Here is where the NPE hits
}
And this cycle will cause ArrayIndexOutOfBoundsException later because in Java valid array indexes start from 0 and go to array.length-1 (0 to 29 in your case), while this code will try to access itemListArray[ 30 ].
It isn't sufficient for you to instantiate your array, you must also populate it with objects. Otherwise each index contains null by default.
private Item[] itemListArray = new Item[30];
for (int i = 0; i < itemListArray.length; i++) {
itemListArray[i] = new Item();
}
You instantiate your array with private Item[] itemListArray = new Item[30]; which creates an array of type Item with 30 null entries.
When you call itemListArray[i].emptySlot in your loop in the constructor you are accessing a variable from a null object.
You will have to instantiate any Item objects in your array in the loop in your constructor (or elsewhere) before you can access any variables or invoke any methods from them.
Also your for loop is skipping the first element. The first element in Java has an index of 0.
I guess you may haven't understand initialization in java.you just initialize a array ,but it haven't refer to the real object.
code like this will help:
for(int i = 1;i < 31; i++){
Item item = new Item();
item.emptySlot = true;
itemListArray[i] = item; //Here is where the NPE hits
}
try to use a constructor in Item class is much better,hope it work.
Creating an array of objects defaults all of them to null. You need to put an object into each element of the array to get rid of this problem.
for (int i = 0; i < itemListArray.length; i++) {
itemListArray[i] = new Item();
}
for (int j = 0; j < itemButtonArray.length; j++) {
itemButtonArray[j] = new JButton();
}

Java array NullPointerException

The code block is listed below:
public static Vertex[] computeSubGraph(Vertex[] AdjList, int[] retiming)
{
Vertex[] subGraph = new Vertex[AdjList.length];
for (int i = 0; i < AdjList.length; i++) {
System.out.println(i);
subGraph[i].nodeDelay = AdjList[i].nodeDelay;
subGraph[i].predecessor = AdjList[i].predecessor;
subGraph[i].mark = AdjList[i].mark;
subGraph[i].starTime = AdjList[i].starTime;
subGraph[i].finishTime = AdjList[i].finishTime;
for (int j = 0; j < AdjList[i].inArcList.size(); j++) {
ArcNode old = AdjList[i].inArcList.get(j);
ArcNode newNode = new ArcNode(old.adjVex, old.arcWeight);
subGraph[i].outArcList.add(newNode);
subGraph[old.adjVex].inArcList.add(newNode);
}
}
return subGraph;
}
This is the Vertex class:
public class Vertex implements Comparable<Vertex> {
public int arcWeight;
public int preDelay;
public boolean infinite = true;
public int nodeDelay = 0;
public Vertex predecessor = null;
public ArcNode firstArc = null;
public int mark = 0;
public int starTime;
public int finishTime;
public ArrayList<ArcNode> inArcList = new ArrayList<ArcNode>();
public ArrayList<ArcNode> outArcList = new ArrayList<ArcNode>();
}
Actually, I just want to copy the element in AdjList to a new array subgraph. But the error message shows that "java.lang.NullPointerException" and shows the problem lies in "subGraph[i].nodeDelay = AdjList[i].nodeDelay;" line.
I tested by printing to the console. And found the AdjList.length is 8 and the problem occurs in the very first round; And even when I only write "subGraph[i].nodeDelay;" without assigning any value to it, it also shows the wrong message.
Any idea on this? Thanks in advance.
Add it inside the loop:
subGraph[i] = new Vertex();
You first need to instantiate an object (subGraph[i] in your case) before accessing it.
The answer is: uninitialized variable. You did initialize subGraph to be an array, but you did not initialize subGraph[i].
When you create an object array in java, it's automatically initialized with null values. It's your responsibility to loop on the array an populate it with references to new objects.
In your case, you should assign Vertex objects to all array positions.
You need to create a Vertex instance and place it in the array prior to setting any fields.
Something like:
public static Vertex[] computeSubGraph(Vertex[] AdjList, int[] retiming)
{
Vertex[] subGraph = new Vertex[AdjList.length];
for (int i = 0; i < AdjList.length; i++) {
subGraph[i] = new Vertex(); // adding instance prior to setting fields.
System.out.println(i);
subGraph[i].nodeDelay = AdjList[i].nodeDelay;
subGraph[i].predecessor = AdjList[i].predecessor;
subGraph[i].mark = AdjList[i].mark;
subGraph[i].starTime = AdjList[i].starTime;
subGraph[i].finishTime = AdjList[i].finishTime;
for (int j = 0; j < AdjList[i].inArcList.size(); j++) {
ArcNode old = AdjList[i].inArcList.get(j);
ArcNode newNode = new ArcNode(old.adjVex, old.arcWeight);
subGraph[i].outArcList.add(newNode);
subGraph[old.adjVex].inArcList.add(newNode);
}
}
return subGraph;
}
On add
subGraph[i] = new Vertex();
before this line
subGraph[i].nodeDelay = AdjList[i].nodeDelay;
Because subGraph[i] is initially null . So subGraph[i].nodeDelay will obviously throw a NullPointerException, because you are trying to access or modify the field of a null object. Array of references will always be initialized with elements of null references by default.

Init array of object and pass values

I know there are plenty of question like this in the forum, but after searching for a good while I havent found the answer. I'm also very new to programming so dont flame me please.
I want to creat 8 objects off my class and pass different values to them.
f.e.
public class exampleClass(){
int value;
}
and then init them:
for(int i=0; i<7; i++){
exampleClass c= new // I get lost at this point
//and how can we pass "i" to the var "value" inside the new objects?
}
thanks a lot!
You need to give ExampleClass a constructor to populate the value. For example:
public class ExampleClass {
private final int counter;
public ExampleClass(int counter) {
this.counter = counter;
}
}
...
ExampleClass[] array = new ExampleClass[7];
for (int i = 0; i < array.length; i++) {
array[i] = new ExampleClass(i);
}

Categories

Resources