这是如何在OOP中重用代码的?

时间:2014-08-08 23:22:22

标签: java arrays oop random

我有一个类,它有一个生成随机数据的方法来填充数组。该类具有在private final Random rnd的构造函数中初始化的数据成员new Random();。这用于为数组生成数据的方法。

例如

package test;

import java.util.Random;

public class WorkWithArrays {

    WorkWithArrays(Object[] arr) {
        rand = new Random();
        fillArrays(arr);
    }

    /*fills arrays with random data;
      since this method is called from constructor
      must be declared final*/
    public final void fillArrays(Object[] arr) {
        //code goes here
    }

    /*some other methods and data members*/

     final private Random rand;
}

我正在编写一个新类,我还需要用随机值填充数组。有没有办法我不能重写相同的方法?我可以extend这个类,或者我可以使方法静态。由于我只需要fillArrays()使其成为static似乎比extend更好的选择。

所以让它静止。

public static final void fillArrays(Object[] arr) {
   //code goes here
}

现在fillArrays()使用rand这是一个问题,因为rand不是静态的。那么为什么不让它静止呢?现在在WorkWithArrays中,我们不再在构造函数中初始化rand,而是将其作为final static private Random rand = new Random();作为数据成员。这是正确的吗?在构造函数之外初始化东西似乎是不好的做法。

现在我可以做到

包裹测试;

MyNewClass {
    someMethod() {
        int[] x = new int[25];
        WorkWithArrays.fillArrays(x);
    }
}

3 个答案:

答案 0 :(得分:2)

这是不错的做法;正如沃伦所指出的,有一个static initializer构造用于此。

例如,要使用类似实用程序的方法创建类('函数' 并不真正需要状态),有几件事你可以做做。

让课程本身最终

这可以防止课程的扩展,这是没有意义的。

public final class WorkWithArrays {
  // ...
}

使构造函数成为私有

这可以防止类被初始化

private WorkWithArrays() {}

创建静态随机数发生器

你可以自己创建/初始化它(根本不是不好的做法!)

private static final Random rand = new Random();

或使用上述静态初始化程序

private static Random rand;
static {
  rand = new Random();
}

请注意final只能与静态属性一起使用,如果它是在线初始化

使随机数组填充方法静态

一样简单

public static void fillArrays(Object[] arr) {
  // code goes here
}

这是实现称为singleton类的设计模式的一种方式,实际上在整个OOP语言中非常常见。

在Java中,不是创建getInstance() - 类型方法,而是通常在本地存储实例(或者根本不创建实例,例如这里的情况),静态方法引用内部存储的实例

初始化逻辑进入static { }初始化程序块,在Java classloader首次加载类时执行。

请注意,在您的示例中(在撰写本文时),您在静态方法上拥有final关键字。 This is not necessary,并且经常被静态分析器捕获为无效/无意义。


我通常不会为OP编写代码,但以下是构建类 1 的完美方法。

public final class WorkWithArrays {
  private static final Random RAND; // = new Random();
  static {
    WorkWithArrays.RAND = new Random();
  }

  private WorkWithArrays() {}

  public static void fillArrays(Object[] array) {
    for (int i = 0, len = array.length; i < len; i++) {
      array[i] = WorkWithArrays.RAND.nextInt();
    }
  }
}

1 导入已被省略

答案 1 :(得分:0)

静态变量通常在构造函数外部初始化。事实上,在Java中,有一个“静态初始化器”的概念,它专门用于初始化任何构造函数之外的静态变量,如果初始化对于简单的赋值来说太复杂了。

答案 2 :(得分:0)

静电越多,离物体方向越远。静态不受多态性的影响,并且很少使用状态来促进数据隐藏(因为所有实例在通过静态变量时都倾向于交叉通信)。

此外,阵列的许多(并非所有)细节也与面向对象的编程不一致,因为数组是数据的持有者而没有组合代码和数据的可能性。因此,数组缺乏行为,并将数据正确性的责任委托给其他不相关的代码片段。

对于面向对象的解决方案:

public class RandomIntList {
   private int[] values;

   public RandomIntList(int size) {
      values = new int[size];
      Random random = new Random();
      for (int i = 0; i < size; i++) {
        values[i] = random.nextInt();
      }
   }

}

请注意,现在您可以清楚地识别哪些对象是RandomIntLists,哪些不是,这对于int []来说是不可能的。

当然,如果你添加像

这样的东西
public int[] asArray() {
   return values;
}

你让猫从包里出来,因为其他代码可以修改类的内部状态而不通过类的边界(也就是接口或方法)。因此,为了使您的类面向对象,您有时需要复制(当数据可以变异时)。

public int[] asArray() {
    return Arrays.copyOf(values, values.size);
}