构造函数重载 - Java中的最佳实践

L.S*_*ner 17 java inheritance constructor instance superclass

构造函数也可以像任何其他方法一样重载,我知道这个事实.由于任务,我决定使用具有多个构造函数的抽象超类:

摘要超类:

protected ListSortierer()
{
  this( null, null );
}

protected ListSortierer( List<E> li )
{
  this( li, null );
}

protected ListSortierer( Comparator<E> comp )
{
  this( null, comp );     
}

protected ListSortierer( List<E> li, Comparator<E> com )
{
  this.original = Optional.ofNullable( li );
  this.comp = Optional.ofNullable( com );
}
Run Code Online (Sandbox Code Playgroud)

要访问每个构造函数,我还需要子类中的多个构造函数.

BubbleSort.java:

public ListBubbleSort()
{
  super();
}

public ListBubbleSort( List<E> li )
{
  super( li );
}

public ListBubbleSort( Comparator<E> com )
{
  super( com );
}

public ListBubbleSort( List<E> li, Comparator<E> com )
{
  super( li, com );
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,子类的每个构造函数都会立即调用超类的构造函数.我想到我可以再次引用自己的构造函数并传递null值:

public ListBubbleSort()
{
  this( null, null );
}

public ListBubbleSort( List<E> li )
{
   this( li, null );
}

public ListBubbleSort( Comparator<E> com )
{
   this( null, com );
}

public ListBubbleSort( List<E> li, Comparator<E> com )
{
   super( li, com );
}
Run Code Online (Sandbox Code Playgroud)

这样做将允许我省略抽象超类中的3个重载构造函数,但会强制每个子类遵循相同的模式.

我的问题是:在一致性的情况下,更好的方法是什么?处理抽象超类或子类中的缺失值?它是否会对实例化产生影响,还是只是意见问题?

And*_*lko 14

在一致性的情况下,更好的方法是什么?

  1. 让所有子构造函数都是私有的.
  2. 介绍静态工厂方法.

    ListBubbleSort.withList(List<E> list)
    ListBubbleSort.withComparator(Comparator<E> comparator)
    
    Run Code Online (Sandbox Code Playgroud)
  3. 调用适当的super构造函数.不要传递任何nulls.

    public static <E> ListBubbleSort withList(List<E> list) {
        return new ListBubbleSort(list);
    }
    
    private ListBubbleSort(List<E>) {
        super(list);
    }
    
    protected ListSortierer(List<E>) {
        // initialise only the list field
        this.origin = list;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 不要Optional用作字段.

    this.original = Optional.ofNullable(li);

  5. 如果您有3个以上的参数,请考虑使用Builder模式.

处理抽象超类或子类中的缺失值?

构造函数应该提供初始值.你没有传递初始值,你只是表明他们的缺席.

默认情况下,null是引用类型的初始值.因此,如果没有给出它的值,则不需要重新分配字段.

它是否会对实例化产生影响,还是只是意见问题?

可读性,维护.


我建议阅读Joshua Bloch撰写的Effective Java:

创建和销毁对象

  • 第1项:考虑静态工厂方法而不是构造函数
  • 第2项:在面对许多构造函数参数时考虑构建器


Gho*_*ica 8

关于问题本身:我认为两种选择都不理想.

您努力编写尽可能少的代码.添加重载只是因为它们看似方便,所以要小心.实际上,你应该反过来:非常认真地考虑你的真实用例是什么,并且只支持那些.

在您的情况下,练习的重点似乎是允许使用不同的实现进行排序.从这个意义上说,你应该更好地研究战略模式.

换句话说:你的第一个想法总是更喜欢构成而不是继承.当你的设计引导你遇到这样的问题时,更好的答案可能是退出你当前的设计并找到一种方法来启用不同的排序作为某种"服务" - 而不是将列表本身一起支持到排序事物中.