我在 JAVA 中创建了一个矩阵类,它由一个带有行变量和列变量的 2D int 数组组成。该类的构造函数生成一个维度为 n x m 的矩阵,我还实现了两个打印矩阵值及其转置的方法(getMatrixValues 和 getTransposedValues
)。
但是,我想创建一个函数,它接受一个矩阵作为输入并返回它的转置,但是由于这个类不是一个数组,如果我正确理解IntelliJ返回给我的异常(“java: array required,but Matrix found”),我就不能使用< code>AT[j][i] = A[i][j]对它进行迭代。显然,我可以简单地使用一个int[][]类来开始,而不是定义一个新的类,但是由于我是JAVA和面向对象编程的新手,我想知道是否有另一种可能性而不丢弃我的Matrix类?
这是我的代码:
import java.util.Random;
import java.util.Arrays;
public class Matrix {
private int n; // rows
private int m; // cols
private int[][] A; // matrix
public static void main(String[] args){
Matrix A = new Matrix(4,4);
A.getMatrixValues();
System.out.println("\n");
A.getTransposedValues();
Matrix AT = transposeMatrix(A);
}
// constructor (randomly generates matrix)
public Matrix(int rows, int cols){
n = rows;
m = cols;
A = new int[rows][cols];
Random r = new Random();
// r.setSeed(1);
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols ; j++)
{
A[i][j] = r.nextInt(10);
}
}
}
// print matrix
public void getMatrixValues(){
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
System.out.print(A[i][j]+"\t");
}
System.out.print("\n");
}
}
// print transposed matrix
public void getTransposedValues(){
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
System.out.print(A[j][i]+"\t");
}
System.out.print("\n");
}
}
public static Matrix transposeMatrix(Matrix A){
Matrix AT = new Matrix(A.get_n(), A.get_m());
for(int i = 0; i < A.get_n(); i++)
{
for(int j = 0; j < A.get_m(); j++)
{
AT[j][i] = A[i][j];
}
}
return AT;
}
// getters
public int get_n(){
return n;
}
public int get_m(){
return m;
}
}
前言
我后来才注意到,在创建转置矩阵时,实际上需要创建m行n列的矩阵
这意味着,在实例化新对象时,您在transposeMatrix()
中混合了m
和
这也意味着您的代码-实际上-只适用于方阵。只需像这样创建对象:
newMatrix(Matrix.get_m(),Matrix.get_n())
注意:我重新命名了变量;参见下文“解决方案”一节。
然而,由于这不是你的问题的一部分,我没有在下面的代码片段中修复它。
Scopes
当在所有其他方法中时,您处于所在对象的词法范围中。这允许您访问它的字段(比如< code>int[][] A)。
但是当在< code > transpose Matrix(Matrix A)内部时,您是在< code>static范围内,也就是说,不在对象的范围内。< br >更令人困惑的是,您的实例变量被称为< code>A,很像< code>transposeMatrix()的参数< code>Matrix A。虽然您可以通过< code>A访问2D数组,但现在您可以通过< code>A访问< code>Matrix对象。这既是因为我们不再是在一个对象中,也是因为新的局部变量覆盖了对类似命名的实例/静态变量的访问(您必须使用< code>this。或< code >矩阵。一个)。
访问修饰符< br >当试图修改您的代码时,您会偶然发现您使用的访问修饰符的限制:< code>private。< code>private int[][] A将使< code>A(您的数组)仅在从对象内部引用时可访问。但是当调用< code>transposeMatrix()时,我们处于静态上下文中,也就是说,不再在您的对象内部。
要解决此问题,可以更改访问修饰符以允许我们从对象外部访问该字段。要启用此功能,可以将修改器更改为任何其他选项,最简单的方法是将其删除。但是,我建议您在官方文档中阅读更多关于Access Modifier的信息。
解决方案
假设我们从int[][]A
中删除了私有
。代码会起作用吗?
不。那是因为我在解释范围时谈到的混乱。为了澄清混乱,让我们重命名一些变量:(将int[][]A
更改为int[][]数组
,Matrix A
到Matrix
,Matrix AT
到Matrix matrixTransposed
)
int[][] array; // <-- Notice the removed access modifier!
// ...
public static Matrix transposeMatrix(Matrix matrix){
Matrix matrixTransposed = new Matrix(matrix.get_n(), matrix.get_m());
for (int i = 0; i < matrix.get_n(); i++) {
for(int j = 0; j < matrix.get_m(); j++) {
matrixTransposed[j][i] = matrix[i][j]; // Won't work!
}
}
}
上述代码仍然存在故障。这是我们现在可以清楚地看到的,因为我们试图访问Matrix
-对象,就像它是一个数组一样。然而,我们需要访问它的实例变量。因此,我们添加了一个<code>,而不是以错误的方式访问数组。数组在每个Matrix
-对象之后,我们试图访问它的数组。
public static Matrix transposeMatrix(Matrix matrix){
Matrix matrixTransposed = new Matrix(matrix.get_n(), matrix.get_m());
for (int i = 0; i < matrix.get_n(); i++) {
for(int j = 0; j < matrix.get_m(); j++) {
matrixTransposed.array[j][i] = matrix.array[i][j]; // NOW we are accessing their arrays respectively
}
}
}
另一种解决方案
通过更改数组的访问修饰符(就像我们上面所做的那样),我们不仅可以覆盖数组的值,还可以覆盖数组本身。
为了限制一个人这样做,我们可以使用“Getters and Setters”。他们就像一个中间人,允许我们只间接访问阵列,但根据需要对阵列进行如此多的控制。
我们可以简单地定义它们,创建两个新方法(因此得名):
public int get(int i, int j) {
return array[i][j];
}
public void set(int i, int j, int value) {
array[i][j] = value;
}
如您所见,我们只是将请求转发给“中间人”,后者会相应地处理它。
注意:我们可能会遇到运行时异常,因为我们没有检查指定索引处的字段是否确实存在。您可能希望在访问它们之前添加一些 if 语句。
通过使用getter和setter,我们可以将代码修改为:
private int[][] array; // We still want to restrict access to 'array'...
// ...
// ...but still allow accessing them, be it indirectly
public int get(int i, int j) {
return array[i][j];
}
public void set(int i, int j, int value) {
array[i][j] = value;
}
// Now using getter and setter
public static Matrix transposeMatrix(Matrix matrix) {
Matrix matrixTransposed = new Matrix(matrix.get_n(), matrix.get_m);
for (int i = 0; i < matrix.get_n(); i++) {
for (int j = 0; j < matrix.get_m; j++) {
matrixTransposed.set(j, i, matrix.get(i, j));
}
}
}
另外
您还应该看看命名约定。它们对于使您的代码发挥作用并不重要,但会使阅读和理解(从而调试)它变得容易得多。
我认为也好的是,看看一个风格指南,看看如何通过简单的技巧使你的代码更具可读性,或者只是在你的代码中有一个一致的风格。我喜欢谷歌的Java风格指南,但是,还有很多其他的。
而且,您不必坚持现有的风格指南,您也可以拥有自己的风格!但尽量保持一致。这使得其他人和你自己将来在重新阅读你的代码时更容易。
我已经将我的站点部署到heroku,现在我正试图将我的本地数据库向上推,但不断得到这个错误: 未知数据库: heroku配置:获取DATABASE_URL 并使用返回的值。我尝试重置DATABASE_URL,但仍然得到相同的错误。如有任何帮助,不胜感激,谢谢!
我遵循了FAQ,但我运行的是Ubuntu10服务器,所以J6是我能得到的最好的。当我启动GWAN4.2.13(sudo./gwan)时,我得到“hello.java:to use.java scripts,install java”
我急需一个建议,我到底哪里出了问题 我有servlet api。jar@E:\J2EE\apache-tomcat-6.0.18\lib E:\J2EE\apache-tomcat-6.0.18\lib\servlet api。罐子 我试图运行一个Servlet类"TouchServlet.java"这是在 E:\J2EE\apache-tomcat-6.0.18\webapps\TouchSer
我用如下命令创建项目 npm init vue@latest 创建过程中选择了pinia,但是main.js中导入pinia模块时不能被识别: import { createPinia } from 'pinia' 这句里面的pinia和Pinia均提示为“Unknown word”.
有25种类型的空白。在下面的代码中显示,25种类型中有4种在Java中不被视为空白。为什么? 参考-https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/character.html#IsWhitespace(char)