静态方法中的重复代码

时间:2018-01-04 09:26:03

标签: java code-duplication

我在JAVA中实现了两个读者。见下文:

public final class ReaderA {
  public ReaderA() {}

  public static int read(final File file) {
    final byte[] data = Files.readAllbytes(file.toPath());
    return read(data);
  }

  public static int read(final byte[] data) {
    // do somethingA
  }

  ...// and some other methods
}


public final class ReaderB {
  public ReaderB() {}

  // this method is exactly the same as in ReaderA
  public static int read(final File file) {
    final byte[] data = Files.readAllbytes(file.toPath());
    return read(data);
  }

  // this is implemented different from the one in ReaderA
  public static int read(final byte[] data) {
    // do somethingB
  }

  ...// and the same other methods as in ReaderA
}

问题。避免重复代码的最佳方法是什么?

我尝试在新的抽象类Reader中提取重复的代码,并尝试制作read(final byte[] data)摘要并在子类ReaderAReaderB中实现它。它不起作用,因为这些方法是静态的。

5 个答案:

答案 0 :(得分:2)

除非您从static中删除read(byte[])修饰符并创建实例,否则您将无法使用继承来帮助您。

static方法的行为与实例方法不同,无法覆盖。相反,超类和子类都将具有需要使用类名限定的单独方法。拉起read(File)意味着它总是调用超类的read(byte[])。您仍然需要将read(File)复制到每个子类,以使其使用该类自己的read(byte[])Ward's answer中的代码也显示了这一点。

供参考,请阅读此问题及其答案:Are static methods inherited in Java?

举例说明:您拥有的两种read(File)方法"完全相同"就像你在你的代码片段中所说的那样。他们不会同时拨打this.read(data),而是拨打ReaderA.read(data)ReaderB.read(data)。了解read(byte[])调用如何处理两种完全不同的,不可覆盖的方法。

如果它在您的权力范围内,我建议以不太静态的方式重写读者:

interface Reader
{
    default int read(File file)
    {
        final byte[] data = Files.readAllbytes(file.toPath());
        return read(data);
    }

    int read(byte[] data);
}

class ReaderA
    implements Reader
{
    int read(byte[] data)
    {
        // do somethingA
    }
}

class ReaderB
    implements Reader
{
    int read(byte[] data)
    {
        // do somethingB
    }
}

注意read(File)现在对于所有实现类是如何相同的。当然,您必须更改从ReaderX.read()new ReaderX().read()调用方法的方式。

答案 1 :(得分:1)

我认为你需要首先问自己几个问题:

  1. 我真的需要两种静态方法吗?
  2. “方法”或类的共同代码是什么?
  3. 编写一个抽象类来编写这样的实现并使ReaderA和ReaderB扩展它,减少重复的代码吗?
  4. 你是否应该有一个父类,然后创建从上面继承的类?
  5. 我认为您应该阅读SOLID原则,特别是开放/封闭原则和依赖性反转

答案 2 :(得分:0)

如果您正在使用Java SE 8,则可以将静态方法放在界面中。 Java接口静态方法类似于默认方法,除了我们不能在实现类中覆盖它们。此功能有助于我们避免在实现类中实现不良而导致意外结果。

答案 3 :(得分:0)

有一些可能性:

  1. 从其中一个类中删除该方法并使用继承(您不能为静态方法调用super.myMethod(),但除非您覆盖它,否则它将起作用)
  2. 我建议不要这样做:你可能会在你的子类中获得其他方法,你可能不想这样做。

    1. 将它提取到两个类的公共超类

    2. 从另一个类中调用该方法。如果两者保持相同的功能,这将起作用

答案 4 :(得分:0)

我不确定使用静态方法保持此实现是最好的,但如果是这样,您可以添加Function参数。

public class Reader {

    public static int read(final File file, Function<byte[], Integer> reader) {
        final byte[] data = Files.readAllbytes(file.toPath());
        return reader.apply(data);
    }

}

然后像这样使用它:

public final class ReaderA {
    public static int read(final File file) {
        return Reader.read(file, ReaderA::read);
    }
    public static int read(final byte[] data) {
        // do somethingA
    }
}

自Java 8中引入functional interfacesmethod references以来,几乎没有任何重复的代码部分无法避免。