Oop 编写长构造函数有什么缺点吗?
它是否会影响加载应用程序的时间?Oop 编写长构造函数有什么缺点吗?,oop,Oop,它是否会影响加载应用程序的时间? 或者在这样做时会遇到其他问题?构造函数是另一个函数。您需要多次调用非常长的函数才能使程序运行缓慢。因此,如果只调用一次,通常与内部有多少代码无关。它自然会影响构造该对象所需的时间,但只不过是拥有一个空构造函数并调用方法来完成该工作。在复制构造函数的情况下,如果我们在这种情况下使用“不使用引用”,则对应用程序加载时间没有影响 它将创建一个对象并调用复制构造函数并传递 值复制到复制构造函数,并且每次创建新对象时 每次调用复制构造函数时,它都会转到无限并 填充内存,然
或者在这样做时会遇到其他问题?构造函数是另一个函数。您需要多次调用非常长的函数才能使程序运行缓慢。因此,如果只调用一次,通常与内部有多少代码无关。它自然会影响构造该对象所需的时间,但只不过是拥有一个空构造函数并调用方法来完成该工作。在复制构造函数的情况下,如果我们在这种情况下使用“不使用引用”,则对应用程序加载时间没有影响 它将创建一个对象并调用复制构造函数并传递 值复制到复制构造函数,并且每次创建新对象时 每次调用复制构造函数时,它都会转到无限并 填充内存,然后显示错误消息 如果我们传递引用,它将不会创建用于存储的新对象
价值。而且不会发生递归关于“长”的含义,问题很模糊。以下是一些可能的解释: 解释#1:构造函数有许多参数 具有许多参数的构造函数可能导致可读性差,并且存在更好的替代方法
这是一个来自java第二版的引用,项目2:在遇到许多构造函数参数时考虑构造器模式:
传统上,程序员使用伸缩构造函数模式,在这种模式中,您只提供一个具有所需参数的构造函数,另一个具有单个可选参数,第三个具有两个可选参数,依此类推 伸缩构造函数模式基本上是这样的: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);
但是,您当前无法仅设置名称
和可调整
,并将级别保留为默认值。您可以提供更多的构造函数重载,但很明显,随着参数数量的增加,这个数量会急剧增加,甚至可能有多个boolean
和int
参数,这会让事情变得一团糟
正如你所看到的,这不是一个令人愉快的模式,使用起来更不愉快(这里“真”是什么意思?13是什么?)
Bloch建议使用builder模式,这将允许您编写如下内容:
Telescope telly = new Telescope.Builder("X/1999").setAdjustable(true).build();
请注意,现在这些参数已命名,您可以按任意顺序设置它们,并且可以跳过希望保留为默认值的参数。这当然比伸缩构造函数好得多,特别是当有大量属于许多相同类型的参数时
另见
< LI> java第二版,第2项:在遇到许多构造函数参数时考虑构造器模式()
相关问题
解释#2:建造师做了大量耗费时间的工作
如果工作必须在构造时完成,那么在构造函数或助手方法中完成工作并不会产生太大的影响。但是,当构造函数将工作委托给助手方法时,请确保它不可重写,因为这可能会导致很多问题
这里引用了《有效Java第二版》第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
时,子项
尚未完成初始化最终整数x
,并且该方法获取了错误的值。这几乎肯定会导致bug和错误
解释#3:构造函数做了很多可以推迟的工作
当某些工作推迟到实际需要时,可以加快对象的构造速度;这称为延迟初始化。例如,当构造字符串时,它实际上不会计算其哈希代码。它仅在第一次需要哈希代码时才执行此操作,然后它将缓存它(因为字符串是不可变的,所以此值不会更改)
但是,考虑有效的java第二版,项目71:明智地使用惰性初始化。延迟初始化可能会导致细微的错误,并且不一定能够提高性能,从而证明增加的复杂性是合理的。不要过早地进行优化。
构造函数有点特殊,因为构造函数中未处理的异常可能会产生奇怪的副作用。如果没有看到您的代码,我会假设长构造函数会增加异常的风险。我将使构造函数尽可能简单,并利用其他方法来完成其余的工作,以便提供更好的错误处理 我会避免在构造函数中执行任何不必要的操作。在那里初始化变量,尽量不要做其他事情。附加功能应该驻留在单独的函数中,只有在需要时才调用这些函数。最大的缺点可能与编写任何其他长函数相同——它可能变得复杂且难以理解
其余的将有所不同。首先,长度和执行时间不一定相关——您可以有一行代码(例如,函数调用)需要几秒钟才能完成(例如,连接到服务器),也可以有大量代码完全在CPU内执行并快速完成