【问题标题】:java array of a class with default value具有默认值的类的java数组
【发布时间】:2016-07-17 10:11:18
【问题描述】:

我有一个有理数类,其构造函数的默认值为 0/1,如下所示:

public Rational (){ this(0, 1);}

public Rational (int numerator, int denominator){
    this.numerator = numerator;

    if (denominator== 0)
        throw new IllegalArgumentException("Denominator can't be zero.");

    this.denominator = denominator;
}

现在,在一个子类中,我想创建一个 Rationals 数组。它们都设置为“null”。所以我在 Rational 类中有两个方法将所有值设置为零。我有一个用于简单数组,另一个用于矩阵:

public Rational[] zero(Rational[] array){
    for (int i=0; i<array.length; i++)
        array[i] = new Rational();

    return array;
}

public Rational[][] zero (Rational[][] matrix){
    for (int i=0; i<matrix.length; i++)
        for(int j=0; j<matrix[i].length; j++)
            matrix[i][j] = new Rational();

    return matrix;
}

首先,使用改进的循环会更好吗?比如:

public Racional[][] zero(Racional[][] matrix){
    for (Racional[] arr : matrix)
        for (Racional rat : arr)
            rat = new Rational();

    return matrix;
}

其次,有没有一种方法可以创建数组或矩阵,而无需像使用原始类型那样手动将所有位置归零。

例如:

int[] arr = new int [10];            //All zero
Rational[] arr = new Rational [10];  //All null
arr = arr.zero (arr);                //All "default" - 0/1

【问题讨论】:

  • 抱歉,据我所知,Java 并没有这样做。
  • 对于原始类型,可以使用Arrays.fill
  • @callyalater Arrays.fill() 也适用于对象,但仅当 Rational 不可变时才适用于此。

标签: java arrays default-value


【解决方案1】:

如果您大量使用 Rational 的数组和矩阵,请考虑在 Rational 类中编写静态辅助方法:

static public Rational[] newArray(int size) {
    Rational[] arr = new Rational[size];
    for (int i = 0; i < size; i++)
        arr[i] = new Rational();
    return arr;
}

static public Rational[][] newMatrix(int h, int w) {
    Rational[][] m = new Rational[h][];
    for (int i = 0; i < h; i++) 
        m[i] = newArray(w);
    return m;
}

然后,要实例化一个填充有默认实例的数组或矩阵,只需调用:

Rational[] array = Rational.newArray(10);

Rational[][] matrix = Rational.newMatrix(10, 5);

【讨论】:

  • 是的。工作得很好。而且很容易理解。
【解决方案2】:

使用不可变的Rational 类,

public static class Rational {
    public final int num, denom;
    public Rational() {num = denom =0;}
    public Rational(int num, int denom) {this.num=num; this.denom=denom;}
}

可以这样做:

public static void zero(Rational[][] mat) {
    Rational def = new Rational();
    for (Rational[] arr : mat) {
        Arrays.fill(arr, def);
    }
}
public static void main (String[] args) throws java.lang.Exception
{
    Rational[][] mat = new Rational[5][5];
    zero(mat);
}

“自动”默认初始化类似于 C++ 在这里是不可能的。此外,嵌套的“新式”for 循环不起作用,因为设置 rat = new Rational() 只会重新分配临时的 rat,而不是数组中的值。

如您所见,这会使用 same 默认Rational 填充矩阵。这是对不可变Rational 的明显性能和内存使用优化,并避免了重复的构造函数调用。如果你有可变的Rational(我不鼓励),这几乎肯定是灾难性的错误:改变一个值会改变它们。在这种情况下,您可能最好使用嵌套的“旧式”for 循环。 (我认为带有内部“旧式”for 循环的外部“新式”for 循环不会那么容易阅读,但肯定是可行的。)

【讨论】:

  • @SashaSalauyou 我认为您在我编辑答案以包含该信息之前发表了评论:-)
  • 由于 Rational 是可变的,所以当我尝试乘法时,我会遇到这样的情况:this.numerator = this.numerator * otherRational.numerator;(分母相同)。并作为回报无效。所以,如果我选择不可变的,我应该像这样更改int num = this.numerator * otherRational.numerator;,然后我返回一个 Rational 作为return new Rational (num, den);。正确的?这样做明智吗?
  • @J.F.这就是如何做到这一点。这样做通常是明智的,但这取决于你。例如,java.lang.String 以这种方式执行所有操作,但您必须确定这是否适合您的需要。在programmers.stackexchange.com/questions/151733 上阅读 cmets,也许在codebetter.com/patricksmacchia/2008/01/13/… 上阅读更多信息。
  • @J.F.该规则的唯一例外是java.util.Date,但Date 的可变性被认为是设计缺陷,并且不推荐使用那里的所有变异方法。
  • @SashaSalauyou 确实。 BigDecimal 中的三个 .valueOf() 方法。并且所有方法都有一个“非空”返回。
猜你喜欢
  • 1970-01-01
  • 2020-09-01
  • 2020-06-14
  • 2014-07-12
  • 1970-01-01
  • 2019-04-03
  • 2018-05-26
  • 1970-01-01
  • 2016-12-13
相关资源
最近更新 更多