Java 中的构造函数重载 - 最佳实践
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1182153/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Constructor overloading in Java - best practice
提问by Eyal Roth
There are a few topics similar to this, but I couldn't find one with a sufficient answer.
有一些与此类似的主题,但我找不到一个有足够答案的主题。
I would like to know what is the best practice for constructor overloading in Java. I already have my own thoughts on the subject, but I'd like to hear more advice.
我想知道 Java 中构造函数重载的最佳实践是什么。我已经对这个主题有了自己的想法,但我想听听更多的建议。
I'm referring to both constructor overloading in a simple class and constructor overloading while inheriting an already overloaded class (meaning the base class has overloaded constructors).
我指的是一个简单类中的构造函数重载和继承一个已经重载的类时的构造函数重载(意味着基类已经重载了构造函数)。
Thanks :)
谢谢 :)
回答by oxbow_lakes
I think the best practice is to have single primary constructorto which the overloaded constructors refer to by calling this()
with the relevant parameter defaults. The reason for this is that it makes it much clearer what is the constructed stateof the object is - really you can think of the primary constructor as the only real constructor, the others just delegate to it
我认为最好的做法是拥有一个主构造函数,重载的构造函数通过调用this()
相关的参数默认值来引用它。这样做的原因是它使对象的构造状态是什么变得更加清楚-实际上您可以将主构造函数视为唯一真正的构造函数,其他构造函数只是委托给它。
One example of this might be JTable
- the primary constructor takes a TableModel
(plus column and selection models) and the other constructors call this primary constructor.
一个例子可能是JTable
- 主构造函数采用TableModel
(加上列和选择模型),其他构造函数调用这个主构造函数。
For subclasses where the superclass already has overloaded constructors, I would tend to assume that it is reasonable to treat any of the parent class's constructors as primaryand think it is perfectly legitimate not to have a single primary constructor. For example,when extending Exception
, I often provide 3 constructors, one taking just a String
message, one taking a Throwable
cause and the other taking both. Each of these constructors calls super
directly.
对于超类已经具有重载构造函数的子类,我倾向于假设将父类的任何构造函数视为主要构造函数是合理的,并且认为没有单个主要构造函数是完全合法的。例如,在扩展时Exception
,我经常提供 3 个构造函数,一个只接受String
消息,一个接受Throwable
原因,另一个接受两者。这些构造函数中的每一个都super
直接调用。
回答by Thorbj?rn Ravn Andersen
If you have a very complex class with a lot of options of which only some combinations are valid, consider using a Builder. Works very well both codewise but also logically.
如果您有一个非常复杂的类,其中有很多选项,其中只有一些组合是有效的,请考虑使用 Builder。在代码上和逻辑上都非常有效。
The Builder is a nested class with methods only designed to set fields, and then the ComplexClass constructor only takes such a Builder as an argument.
Builder 是一个嵌套类,其方法仅用于设置字段,然后 ComplexClass 构造函数只将这样的 Builder 作为参数。
Edit: The ComplexClass constructor can ensure that the state in the Builder is valid. This is very hard to do if you just use setters on ComplexClass.
编辑: ComplexClass 构造函数可以确保 Builder 中的状态有效。如果你只是在 ComplexClass 上使用 setter,这是很难做到的。
回答by Gregory Mostizky
It really depends on the kind of classes as not all classes are created equal.
这实际上取决于类的类型,因为并非所有类都是平等的。
As general guideline I would suggest 2 options:
作为一般准则,我会建议 2 个选项:
- For value & immutableclasses (Exception, Integer, DTOs and such) use single primary constructoras suggested in above answer
- For everything else (session beans, services, mutable objects, JPA & JAXB entities and so on) use default constructor onlywith sensible defaults on all the properties so it can be used without additional configuration
- 对于值和不可变类(异常、整数、DTO 等),请按照上述答案中的建议使用单个主构造函数
- 对于其他所有内容(会话 bean、服务、可变对象、JPA 和 JAXB 实体等),仅使用默认构造函数,所有属性均使用合理的默认值,因此无需额外配置即可使用
回答by Spoike
While there are no "official guidelines" I follow the principle of KISS and DRY. Make the overloaded constructors as simple as possible, and the simplest way is that they only call this(...). That way you only need to check and handle the parameters once and only once.
虽然没有“官方指南”,但我遵循 KISS 和 DRY 的原则。使重载的构造函数尽可能简单,最简单的方法是它们只调用 this(...)。这样你只需要检查和处理参数一次并且只需要一次。
public class Simple {
public Simple() {
this(null);
}
public Simple(Resource r) {
this(r, null);
}
public Simple(Resource r1, Resource r2) {
// Guard statements, initialize resources or throw exceptions if
// the resources are wrong
if (r1 == null) {
r1 = new Resource();
}
if (r2 == null) {
r2 = new Resource();
}
// do whatever with resources
}
}
From a unit testing standpoint, it'll become easy to test the class since you can put in the resources into it. If the class has many resources (or collaborators as some OO-geeks call it), consider one of these two things:
从单元测试的角度来看,测试类会变得很容易,因为您可以将资源放入其中。如果班级有很多资源(或一些 OO 极客称之为合作者),请考虑以下两件事之一:
Make a parameter class
制作参数类
public class SimpleParams {
Resource r1;
Resource r2;
// Imagine there are setters and getters here but I'm too lazy
// to write it out. you can make it the parameter class
// "immutable" if you don't have setters and only set the
// resources through the SimpleParams constructor
}
The constructor in Simple only either needs to split the SimpleParams
parameter:
Simple 中的构造函数只需要拆分SimpleParams
参数:
public Simple(SimpleParams params) {
this(params.getR1(), params.getR2());
}
…or make SimpleParams
an attribute:
...或创建SimpleParams
一个属性:
public Simple(Resource r1, Resource r2) {
this(new SimpleParams(r1, r2));
}
public Simple(SimpleParams params) {
this.params = params;
}
Make a factory class
制作工厂类
Make a factory class that initializes the resources for you, which is favorable if initializing the resources is a bit difficult:
制作一个为你初始化资源的工厂类,如果初始化资源有点困难,这是有利的:
public interface ResourceFactory {
public Resource createR1();
public Resource createR2();
}
The constructor is then done in the same manner as with the parameter class:
然后以与参数类相同的方式完成构造函数:
public Simple(ResourceFactory factory) {
this(factory.createR1(), factory.createR2());
}
Make a combination of both
将两者结合起来
Yeah... you can mix and match both ways depending on what is easier for you at the time. Parameter classes and simple factory classes are pretty much the same thing considering the Simple
class that they're used the same way.
是的...您可以混合搭配两种方式,具体取决于当时对您来说更容易的方式。考虑Simple
到它们以相同方式使用的类,参数类和简单的工厂类几乎是一样的。
回答by Shiva
Well, here's an example for overloaded constructors.
好吧,这里有一个重载构造函数的例子。
public class Employee
{
private String name;
private int age;
public Employee()
{
System.out.println("We are inside Employee() constructor");
}
public Employee(String name)
{
System.out.println("We are inside Employee(String name) constructor");
this.name = name;
}
public Employee(String name, int age)
{
System.out.println("We are inside Employee(String name, int age) constructor");
this.name = name;
this.age = age;
}
public Employee(int age)
{
System.out.println("We are inside Employee(int age) constructor");
this.age = age;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
}
In the above example you can see overloaded constructors. Name of the constructors is same but each constructors has different parameters.
在上面的示例中,您可以看到重载的构造函数。构造函数的名称相同,但每个构造函数的参数不同。
Here are some resources which throw more light on constructor overloading in java,
这里有一些资源可以更多地了解 Java 中的构造函数重载,
构造函数。
回答by Khatri
Constructor overloading is like method overloading. Constructors can be overloaded to create objects in different ways.
构造函数重载类似于方法重载。可以重载构造函数以不同的方式创建对象。
The compiler differentiates constructors based on how many arguments are present in the constructor and other parameters like the order in which the arguments are passed.
编译器根据构造函数中存在的参数数量和其他参数(如参数传递的顺序)来区分构造函数。
For further details about java constructor, please visit https://tecloger.com/constructor-in-java/
有关 java 构造函数的更多详细信息,请访问https://tecloger.com/constructor-in-java/