我没有得到这个java代码的任何输出.当我运行代码而不调用方法时,所有的代码都在主方法中,它工作了



'这声明了matrixA, randomNumber和size'

static int size;
static int matrixA [][] = new int [size][size];
static Random randomNumber = new Random();

'这个方法要求用户输入一个int类型。输入用于设置数组的大小

static void setSize() {
Scanner input = new Scanner(System.in);
System.out.println("Enter size");
size = input.nextInt();
}

'这个方法用随机数填充数组并打印数组。这没有输出。

static void fillMatrixA() {
for (int i = 0; i < matrixA.length; i++) {
System.out.println();
for (int j = 0; j < matrixA[i].length; j++) {
matrixA[i][j] = randomNumber.nextInt(10);
System.out.println(matrixA[i][j]);
}
}
}

'当我在主方法中调用这个方法时,没有输出。这个项目只有一个类。问题是什么?'

当事情看起来不对劲时,(a)检查你的假设,(b)使用调试器。

假设matrixA的长度大于0是不正确的。调试器会显示长度为零。

当您在声明语句中初始化static变量时,该代码将在加载类时执行。所以new int [size] [size]很早就执行了,在其他代码之前。当这一行执行时,它使用size的当前值,它是零。为什么是零?因为这是赋给原语int的默认值。

之后,在setSize方法中,您将size的值从0更改为用户输入的值。但这对二维数组没有影响。在setSize方法执行之前,该数组被初始化为长度为0的值。

看到你的代码运行在Ideone.com上生活。你可以fork这段代码,并使用它。

您遇到的问题是我喜欢在构造函数中进行所有初始化的原因之一。我很少使用初始化声明语法。但是其他理智的程序员在这一点上可能会有不同的看法。


顺便说一下,你的代码还有很大的改进空间。

首先,您可能会过度使用static。任何标记为static的东西都不是面向对象的。如果您用Java编写了很多非面向对象的代码,那么您就错过了Java的很多价值。作为Java的初学者,通常应该避免使用static。即使在实际工作中,通常也将static作为最后的手段。

另一个提示:

  • 将用户界面代码与业务逻辑代码分开。
  • 一般使用本地状态。避免使用全局变量。传递需要的信息作为参数
  • 关闭你的资源,如Scanner使用完成后。使用try-with-resources语法可以更简单、更简单地完成这个任务。
  • 考虑使用static工厂方法而不是public构造函数。

考虑到这些,写一个类来表示我们的问题域,管理一个高和宽是等维的矩阵。

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 ;
}
}

注意这个类有一个特定的目的:管理矩阵的内容。它是而不是负责与用户交互。不是负责运行我们更大的应用程序。

还要注意如何包含二维数组,并标记为private。这在OOP中被称为封装。通过封装,我们今天可以自由地在内部使用二维数组,同时为将来使用其他数据结构留下余地。其他调用SquareMatrix类的代码不知道或不关心它的内部结构。

注意toArray方法是如何复制内部管理的二维数组的。出于几个原因,我们不想提供对内部数组的直接访问。一个原因是直接访问将破坏上面讨论的封装。另一个原因是我们不能信任调用程序的程序员;他/她可以修改内容。

接下来我们创建一个"应用程序"类,以提供访问赏金(即方阵)的用户体验。

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;
}
}
}

注意这里与用户交互以收集输入的代码是如何被隔离到它自己的方法中的。用户界面代码不知道,也不关心矩阵。

运行时。

Enter size: 
3
report = 
[9, 3, 7]
[0, 7, 2]
[0, 7, 7]
array.length: 3