When things seem screwy, (a) check your assumptions, (b) engage a debugger.
Your assumption that matrixA
has a length greater than zero is incorrect. A debugger would show the length to be zero.
When you initialize a static
variable within the declaration statement, that code executes when the class is loaded. So new int [size] [size]
executed very early, before your other code. When that line executed, it used the current value of size
, which was zero. Why zero? Because that is the default value assigned to a primitive int
.
Later, in your setSize
method, you change the value of size
from zero to the value input by the user. But that has no effect on your two-dimensional array. That array was initialized to a length of zero long before the setSize
method executed.
See your code run live at Ideone.com. You can fork that code, and play with it.
The problem you experienced is one reason why I like to do all my initializing within a constructor. I rarely use initialization with declaration syntax. But other reasonable programmers may differ on this point.
By the way, your code has much room for improvement.
First and foremost, you are likely overusing static
. Anything marked static
is not object-oriented. If you are writing much non-object-oriented code in Java, you are missing out on much of the value of Java. As a beginning student of Java, you should generally avoid using static
in general. Even in real work, use static
as a last-resort generally.
Another tip:
- Separate user-interface code from business logic code.
- Use local state generally. Avoid global variables. Pass needed info as arguments.
- Close your resources such as
Scanner
when done using them. Use try-with-resources syntax to do so more easily and briefly.
- Consider using a
static
factory method rather than a public
constructor.
Taking that all into account, write a class to represent our problem domain, the business matter of managing a matrix whose height and width are of equal dimensions.
package work.basil.example.squarematrix;
import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;
public class SquareMatrix
{
private int matrix[][];
private SquareMatrix ( final int size )
{
// … Add code here validate passed argument.
this.matrix = new int[ size ][ size ];
this.randomize();
}
public static SquareMatrix ofSize ( final int size )
{
return new SquareMatrix( size );
}
public void randomize ( )
{
for ( int[] row : matrix )
{
for ( int columnIndex = 0 ; columnIndex < row.length ; columnIndex++ )
{
row[ columnIndex ] = ThreadLocalRandom.current().nextInt( 0 , 10 ); // ( inclusive , exclusive )
}
}
}
public int[][] toArray ( )
{
// Code taken from: https://stackoverflow.com/a/53397359/642706
int[][] copy = Arrays.stream( this.matrix ).map( int[] :: clone ).toArray( int[][] :: new );
return copy;
}
public CharSequence report ( )
{
StringBuilder sb = new StringBuilder();
for ( int[] row : this.matrix )
{
sb.append( Arrays.toString( row ) );
sb.append( "\n" ); // Using Unix convention of LINE FEED as a delimiter. https://www.fileformat.info/info/unicode/char/000a/index.htm
}
return sb ;
}
}
Notice how this class has a specific purpose: manage the content of our matrix. It is not responsible for interacting with a user. It is not responsible for running our larger app.
Also notice how the two-dimensional array is contained, and marked private
. This is known as encapsulation in OOP. By encapsulating, we are free to internally use a two-dimensional array today, while leaving the door open to using some other data structure tomorrow. Other code calling upon our SquareMatrix
class does not know or care anything about its internals.
And notice how the toArray
method makes a copy of our internally-managed two-dimensional array. We do not want to provide direct access to our internal array, for a couple reasons. One reason is that direct access would break the encapsulation discussed above. Another reason is that we cannot trust the calling programmer; he/she may alter the content.
Next we create an "app" class, to provide a user-experience for accessing the bounty that is our square matrix.
package work.basil.example.squarematrix;
import java.util.Scanner;
public class SquareMatrixApp
{
public static void main ( String[] args )
{
SquareMatrixApp app = new SquareMatrixApp();
int size = app.askUserForSize();
SquareMatrix squareMatrix = SquareMatrix.ofSize( size );
CharSequence report = squareMatrix.report();
System.out.println( "report = \n" + report );
int[][] array = squareMatrix.toArray();
System.out.println( "array.length: " + array.length );
}
private int askUserForSize ( )
{
try (
Scanner scanner = new Scanner( System.in ) ;
)
{
System.out.println( "Enter size: " );
int size = scanner.nextInt();
// … Add code here to validate inputs. For example, no negative numbers allowed.
return size;
}
}
}
Notice here how the code for interacting with the user to gather input is segregated to its own method. That user-interface code does not know about, nor does it care about, matrices.
When run.
Enter size:
3
report =
[9, 3, 7]
[0, 7, 2]
[0, 7, 7]
array.length: 3