是否会影响加载应用程序的时间? 或者这样做的任何其他问题?
答案 0 :(得分:24)
问题是“长”意味着什么含糊不清。以下是一些可能的解释:
具有许多参数的构造函数可能导致可读性差,并且存在更好的替代方案。
以下是 Effective Java 2nd Edition的引用,第2项:在面对许多构造函数参数时考虑构建器模式:
传统上,程序员使用 telescoping构造函数模式,在该模式中,您只提供构造函数所需的参数,另一个使用单个可选参数,第三个使用两个可选参数,依此类推。 ..
伸缩构造函数模式基本上是这样的:
public class Telescope {
final String name;
final int levels;
final boolean isAdjustable;
public Telescope(String name) {
this(name, 5);
}
public Telescope(String name, int levels) {
this(name, levels, false);
}
public Telescope(String name, int levels, boolean isAdjustable) {
this.name = name;
this.levels = levels;
this.isAdjustable = isAdjustable;
}
}
现在您可以执行以下任何操作:
new Telescope("X/1999");
new Telescope("X/1999", 13);
new Telescope("X/1999", 13, true);
但是,您目前无法仅设置name
和isAdjustable
,并且默认保留levels
。你可以提供更多的构造函数重载,但显然随着参数数量的增加,数字会爆炸,你甚至可能有多个boolean
和int
参数,这实际上会让事情搞得一团糟。 / p>
正如你所看到的,这不是一个令人愉快的写作模式,使用起来也不那么令人愉快(“真实”在这里意味着什么?13是什么?)。
Bloch建议使用一个构建器模式,这样你就可以编写类似这样的内容:
Telescope telly = new Telescope.Builder("X/1999").setAdjustable(true).build();
请注意,现在参数已命名,您可以按任何顺序设置它们,并且可以跳过要保留默认值的参数。这肯定比伸缩构造函数好得多,特别是当存在大量属于许多相同类型的参数时。
如果工作必须在构造时完成,那么在构造函数或辅助方法中完成它并不会产生太大的差别。但是,当构造函数将工作委托给辅助方法时,请确保它不可覆盖,因为这可能会导致很多问题。
以下是来自 Effective Java 2nd Edition,第17项:设计和继承文档的引用,或者禁止它:
为了允许继承,类必须遵守一些限制。 构造函数不得直接或间接调用可覆盖的方法。如果违反此规则,将导致程序失败。超类构造函数在子类构造函数之前运行,因此在子类构造函数运行之前将调用子类中的重写方法。如果重写方法依赖于子类构造函数执行的任何初始化,则该方法将不会按预期运行。
以下是一个例子来说明:
public class ConstructorCallsOverride {
public static void main(String[] args) {
abstract class Base {
Base() { overrideMe(); }
abstract void overrideMe();
}
class Child extends Base {
final int x;
Child(int x) { this.x = x; }
@Override void overrideMe() {
System.out.println(x);
}
}
new Child(42); // prints "0"
}
}
此处,当Base
构造函数调用overrideMe
时,Child
尚未完成初始化final int x
,并且该方法的值不正确。这几乎肯定会导致错误和错误。
当某些工作被推迟到实际需要时,可以更快地构建对象;这称为延迟初始化。例如,当构造String
时,它实际上不会计算其哈希码。它只在首次需要哈希码时才会这样做,然后它会缓存它(因为字符串是不可变的,这个值不会改变)。
但是,请考虑 Effective Java 2nd Edition,Item 71:明智地使用延迟初始化。延迟初始化可能会导致细微的错误,并且不会总是产生改进的性能,从而证明增加了复杂性。不要过早地优化。
答案 1 :(得分:1)
构造函数有点特殊,因为构造函数中的未处理异常可能会产生奇怪的副作用。在没有看到你的代码的情况下,我会假设一个长构造函数会增加异常的风险。我会使构造函数尽可能简单,并利用其他方法来完成其余的工作,以便提供更好的错误处理。
答案 2 :(得分:1)
最大的缺点可能与编写任何其他长函数相同 - 它可能变得复杂且难以理解。
其余的将会有所不同。首先,长度和执行时间不一定相关 - 你可能有一行(例如,函数调用)需要几秒钟才能完成(例如,连接到服务器)或许多代码完全在CPU并快速完成。
启动时间(显然)仅受启动期间调用的构造函数的影响。我在编写的任何代码中都没有遇到过这个问题(最近都是这样),但是我看到了代码。在某些类型的嵌入式系统(例如)中,您确实希望避免在正常使用期间创建和销毁对象,因此您可以在启动期间静态创建几乎所有内容。一旦运行,您可以将所有处理器时间用于完成实际工作。
答案 3 :(得分:0)
构造函数是另一个功能。您需要多次调用非常长的函数才能使程序运行缓慢。因此,如果它只被调用一次通常无关紧要内部代码。
答案 4 :(得分:0)
它自然会影响构造该对象所花费的时间,但仅仅是拥有一个空构造函数并调用方法来代替它。它对应用程序加载时间没有影响
答案 5 :(得分:0)
在复制构造函数的情况下,如果在那种情况下使用donot use reference 它将创建一个对象并调用复制构造函数并传递 复制构造函数的值以及每次创建新对象时的值 每次它将调用复制构造函数,它将无限和 填充内存然后显示错误信息。
如果我们传递引用,它将不会创建用于存储的新对象 价值。并且不会发生递归
答案 6 :(得分:0)
我会避免在你的构造函数中做任何不必要的事情。在那里初始化你的变量,尽量不要做太多其他事情。其他功能应该驻留在您需要时调用的单独函数中。