Initializing an array of variables within a class instance in Java - java

I'm coming from a C background, and am running into a problem in Java. Currently, I need to initialize an array of variables within an array of objects.
I know in C it would be similar to malloc-ing an array of int within an array of structs like:
typedef struct {
char name;
int* times;
} Route_t
int main() {
Route_t *route = malloc(sizeof(Route_t) * 10);
for (int i = 0; i < 10; i++) {
route[i].times = malloc(sizeof(int) * number_of_times);
}
...
So far, in Java I have
public class scheduleGenerator {
class Route {
char routeName;
int[] departureTimes;
}
public static void main(String[] args) throws IOException {
/* code to find number of route = numRoutes goes here */
Route[] route = new Route[numRoutes];
/* code to find number of times = count goes here */
for (int i = 0; i < numRoutes; i++) {
route[i].departureTimes = new int[count];
...
But its spitting out a NullPointerException. What am I doing wrong, and is there a better way to do this?

When you initialize your array
Route[] route = new Route[numRoutes];
there are numRoutes slots all filled with their default value. For reference data types the default value is null, so when you try to access the Route objects in your second for loop they are all null, you first need to initialize them somehow like this:
public static void main(String[] args) throws IOException {
/* code to find number of route = numRoutes goes here */
Route[] route = new Route[numRoutes];
// Initialization:
for (int i = 0; i < numRoutes; i++) {
route[i] = new Route();
}
/* code to find number of times = count goes here */
for (int i = 0; i < numRoutes; i++) {
// without previous initialization, route[i] is null here
route[i].departureTimes = new int[count];

Route[] route = new Route[numRoutes];
In java when you create an array of Objects, all the slots are declared with there default values as below
Objects = null
primitives
int = 0
boolean = false
these numRoutes slots all filled with their default value i.e. null. When you try to access the Route objects in your loop the array reference is pointing to null, you first need to initialize them somehow like this:
// Initialization:
for (int i = 0; i < numRoutes; i++) {
route[i] = new Route();
route[i].departureTimes = new int[count];
}

for (int i = 0; i < numRoutes; i++) {
route[i] = new Route();
route[i].departureTimes = new int[count];

Related

OutOfBounds when working with objects in an array

When I am creating an array of Example objects, I call something like initializeArray(); I use a simple nested for loop to traverse through the array and then assign new objects with values to each index of the array using exampleArr[i][j] = new Example(false, false, false, 0); however, calling this gives me an java.lang.ArrayIndexOutofBoundsException:0 at the line above.
I am assuming that I am instantiating the new object incorrectly, as this also happens in another method which is supposed to display all of the Example objects in the array. However, I will post the nested loop I am using in case there is something that i've done wrong that I can't see.
public void initializeArray(){
for(int i = 0; i < getRows(); i++){
for(int j = 0; j < getColumns(); j++){
tileArr[i][j] = new Tile(false, false, false, 0);
}
}
}
//Declaration of rows and columns
private int rows;
private int columns;
Tile[][] tileArr = new Tile[rows][columns];
public void setRows(int r)
{
rows = r;
}
public void setColumns(int c)
{
//various setters and getters for the array
columns = c;
}
public int getRows()
{
System.out.print(rows);
return rows;
}
public int getColumns()
{
System.out.print(columns);
return columns;
}
Thanks everyone for your help! The problem has been solved.
Declare your tileArr at the top but do not initialize.
Tile[][] tileArr;
Then initialize your array before your for loop in the initializeArray() (This is assuming your rows and columns is set. You can add logic to check this as well).
tileArr = new Tile[getRows()][getColumns()];
tileArr = new Tile[rows][columns]; //Do this instead if you don't want the print statements to be called
As #gonzo said you have got to initialize your array to allocate enough memory for all the positions you are going to be using.
Tile[][] tileArr;
public void initializeArray(){
Tile[][] tileArr = new Tile[getRows()][getColumns()];
for(int i = 0; i < getRows(); i++){
for(int j = 0; j < getColumns(); j++){
tileArr[i][j] = new Tile(false, false, false, 0);
}
}
return titleArr;
}
//...wherever you want it
this.tileArray = this.initializeArray()
But there are cases when you don't know how big this array may be. For those cases you should be using List<Tile> type like LinkedList<Tile> or ArrayList<Tile> so that you don't need to allocate space for every new position to use.

Java - Array <init> error

So, I have this class, that contains another class array, and in the constructor I want to make "n" and "nCod" equal 0.
public class ITable
{
TableRow arr[];
class TableRow
{
long n;
int nCod;
ICode cod;
}
ITable()
{
arr = new TableRow[256];
for(int i=0;i<256;i++)
{
arr[i].n = 0;
arr[i].nCod = 0;
}
}
}
When I run it, Eclipse console tells me:
java.lang.NullPointerException
at jhuffman.def.ITable.<init>(ITable.java:21)
That line is:
arr[i].n = 0;
When you create an array instance with new TableRow[256], each of its elements are initialized to null.
Therefore, each element should be initialized before being accessed :
arr = new TableRow[256];
for(int i=0;i<256;i++)
{
arr[i] = new TableRow (); // add this
arr[i].n = 0;
arr[i].nCod = 0;
}
When you create an object array with no initial values, all the positions in the array will point to null. So, for example, arr = new TableRow[3] would initialize the array as [null, null, null].
Since you did not store any TableRow objects into arr, when you access arr[i], it returns null instead of a concrete object. If you try to access a field in null it will result in a NullPointerException as you have observed.
What you need to do is create the TableRow instances and place them into the array before you try to access them. Something like this:
arr = new TableRow[256];
for (int i = 0; i < arr.length; i++) {
arr[i] = new TableRow();
arr[i].n = 0;
arr[i].nCode = 0;
}

Fluctuating array sizes

When I learned java, I was told that once created, the size of an array was fixed and couldn't be changed. Recently I've been using arrays a lot and have noticed that code similar to the following doesn't generate errors:
public class Test {
private static String[][] smallArray = new String[4][4];
private static String[][] biggerArray = new String[21][21];
private static String[][] assignedLater;
public static void main(String args[]){
for(int i = 0; i < smallArray.length; i++){
for(int j = 0; j < smallArray[0].length; j++){
smallArray[i][j] = i + j + "";
}
}
for(int i = 0; i < biggerArray.length; i++){
for(int j = 0; j < biggerArray[0].length; j++){
biggerArray[i][j] = i + j + "";
}
}
assignedLater = smallArray;
//last element of last row
System.out.println(assignedLater[3][3]) //returns 6
assignedLater = biggerArray;
//new last element of new last row
System.out.println(assignedLater[20][20]) //returns 40
}
}
After playing around with this for a bit, I ended up testing the following:
public class Test {
private static String[][] smallArray = new String[2][4];
private static String[][] biggerArray = new String[2][21];
private static String[][] errorArray = new String[3][21];
private static String[][] assignedLater = new String[2][0];
public static void main(String args[]){
//fill arrays as in previous example
assignedLater = smallArray;
//last element of last row
System.out.println(assignedLater[1][3]) //returns 6
assignedLater = biggerArray;
//new last element of new last row
System.out.println(assignedLater[1][20]) //returns 21
assignedLater = errorArray; //no error
System.out.println(assignedLater[2][20]); // returns 22
}
}
What's going on here?
Edit
Thanks for the responses, I am hereby enlightened as to why the impossible isn't actually happening.
You are not changing the size of arrays. You are just changing the reference to point to a different array in memory.
The arrays do not change size at all, what you are doing is making the varibles change reference, they will simply change which array they point to without those arrays changing size.
As Juned said you're just changing the reference so you don't need such a complicated example to demonstrate. Even this will suffice:
int[] smallArr = new int[5];
int[] bigArr = new int[5000];
smallArr = bigArr;
System.out.println(smallArr.length); // -> prints 5000...
but we still haven't changed the length of a static array, just changed the location to which smallArr refers to be where bigArr refers.
In your second block, when you have this line, you gave 'assignedLater' some dimensions:
private static String[][] assignedLater = new String[2][0];
But then, in your main function, you pointed it to different arrays, so the old dimensions no longer matter:
assignedLater = smallArray;
After this, any call to assignedLater indices will point to smallArray indices. (until you reassign it again later). And so on.

Understanding constructors and "this"

I'm learning constructors and I understand them for the most part, but I must not understand it enough. I also don't understand this fully. But this code below is supposed to use these constructors:
default constructor, which will be used to fill the matrix with random doubles
constructor which takes a File object, which points to a file
containing a matrix,
constructor which takes a string, which contains the name of the file
constructor which takes a value of type Matrix, and makes a copy of it
constructor which takes a 2D array, and copies its values
And some more, along with a static multiply method. I am supposed to use the commands that are found in main. But I don't quite understand how using a String as the only parameter will do the constructor it's told to, and also the other ones like the default constructor that fills the array with random doubles. I think I should be using this more in my code, but I'm not quite sure.
I mainly just need to be able to set a matrix, fill m1 matrix with random doubles, do it again with m2 matrix, and then use the static multiply method to multiply them, then output the resulting matrix. Thank you.
(Just a heads up, I'm using a 3 by 3 matrix, originally I was supposed to set the size of the matrix to the one found in the text file, but I can also specify the size I want, which I am. And sorry for the messy code. It got all jumbled up while I was trying to figure this stuff out, and I'm afraid of altering it further.)
public class Matrix {
double A[][] = new double[3][3]
// Matrix file name
public Matrix(String name) {
this(new File(name));
}
// Matrix random fill
public Matrix() {
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
this.A[i][j] = (min + Math.random() * (max - min));
}
// Matrix copy
public Matrix(double[][] A) {
private double[][] arrcopy = new double[3][3];
private double[][] array = new double[3][3];
array = A;
for(int i = 0; i < 3; ++i){
for(int j = 0; j < array[i].length; ++j) {
arrcopy[i][j] = array[i][j];
}
}
}
// Set array from text file
public Matrix(File a) {
File f = a;
Scanner inputStreamOne = null;
try{
inputStreamOne = new Scanner(f);
}
catch(FileNotFoundException e){
System.out.printf("Error\n");
}
double arrayOne[][] = new double[3][3];
while(inputStreamOne.hasNextInt()) {
for(int i = 0; i < 3; ++i){
for(int j = 0; j < arrayOne[i].length; ++j){
arrayOne[i][j] = inputStreamOne.nextInt();
}
}
inputStreamOne.close();
}
}
// Gets array in file from string name
public Matrix(String a) {
String inputOne = a;
Scanner inputStreamOne = null;
try{
inputStreamOne = new Scanner(new File(inputOne));
}
catch(FileNotFoundException e){
System.out.printf("Error\n");
}
while(inputStreamOne.hasNextInt()){
for(int i = 0; i < size; ++i){
for(int j = 0; j < arrayOne[i].length; ++j){
arrayOne[i][j] = inputStreamOne.nextInt();
}
}
inputStreamOne.close();
}
}
public static multiply
public static void main(String args[]) {
Matrix m = new Matrix("matrix1.txt");
Matrix m2 = new Matrix("matrix2.txt");
Matrix r = Matrix.multiply(m, m2);
r.output(...);
}
}
Within a constructor or a method this refers to the current object. Within a constructor, if you just use a bare this ( which is to say this without a .method after it ) then it refers to another constructor of the same object that has a different type signature.
Constructors, like any function in Java, can be overloaded. Which is to say, because of Java's type system you can have multiple functions that are of the same name so long as they have different type signatures.
class Foo {
public Foo ( String arg ) {
this(arg, "World");
}
public Foo ( String arg1, String arg2 ) {
// do stuff with arg1 and arg2
}
}
In the above example, one constructor takes a single string and the other takes two. Java won't magically know what to do with the data passed into different constructors. What you have to do is write code in each method so that the resulting object is the same. ( Well technically you don't have to do that, but it's good form ( usually overloaded constructors are for setting default values or for the ease of use of other programmers ))
The this keyword refers to the current object in a constructor or a method, i.e. the object whose constructor or method is being called. Within a constructor, you can also use this to call another constructor in the class.
Refer to http://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html for a clear explanation from Java Tutorials.

The type of an expression must be an array type, but it is resolved to Object

I expected this to compile, but I kept getting the error "The type of an expression must be an array type, but it is resolved to Object". Is there a simple workaround for this?
public class NodeTest {
public static void main(String[] args) {
Object[] arr = new Object[5]; // each element of object will be an array of integers.
for(int i = 0; i < 5; i++){
int[][] a = new int[2*(i+1)][2*(i+1)];
arr[i] = a;
}
arr[0][0][0] = 0; //error here
}
}
arr is Object[] so arr[0] will return an Object
But since you know that arr contains int[][] as instance of Object you will have to cast them to be so.
( ( int[][] ) arr[0] )[0][0] = 0;
You want to declare arr as int[][][] rather than Object[]. While arrays are of type Object so the assignment in the loop is legal, you're then losing that type information so the compiler doesn't know the elements of arr are int[][] in the bottom line.
int[][][] arr = new int[5][][];
for(int i = 0; i < arr.length; i++) { //good practice not to hardcode 5
arr[i] = new int[2*(i+1)][2*(i+1)];
}
arr[0][0][0] = 0; //compiles
I would suggest think from the logic perspective rather than work around.
You are trying to use multidimensional arrays , your looping is in a single dimension{which might be right as per your requirements}. Can you post the pseudo code, this might help
This also works
public class NodeTest {
public static void main(String[] args) {
Object[] arr = new Object[5]; // each element of object will be an array
// of integers.
for (int i = 0; i < 5; i++) {
int[][] a = new int[2 * (i + 1)][2 * (i + 1)];
arr[i] = a;
}
arr[0] = 0; // Make it one dimensional
}
}

Categories