Java支持构造函数重载(当java类包含多个构造函数时,它被称为构造函数重载)。一个类可以有多个构造函数,只要它们的签名(参数)不相同。所以你可以根据需要定义许多构造函数。没有限制。这里有一个例子:-
class Demo {
private String name;
private String city;
private Double salary;
public Demo() {
}
public Demo(String name) {
this.name = name;
}
public Demo(Double salary) {
this.city = city;
}
public Demo(String name,String city) {
this.name = name;
this.city = city;
}
}
与lambda的最大数量或嵌套方法调用的最大数量一样,由于正式指定的类文件格式或编译器限制或bug,我们必须区分正式的Java语言规范和技术限制。
通常,语言规范没有对构造函数的数量进行任何限制。因此,只有一个实际限制,即类声明必须以字节码格式表示。
构造函数被编译成特殊的方法(名为
常量池也有其他用途,比如保存这个类的声明,超级类和
Code
属性的名称,这是有构造函数时需要的,以及我们必须调用的超级类构造函数的链接信息,所以这是类文件端的限制因素。
所以所需的最小常量池条目是
超类名(修改UTF8条目)
- 超类(type Class,指1.)
- 这个类名(修改了UTF8条目)
- 这个类(类型Class,指3.)
- 构造函数的方法名
考虑到这些必需的条目和65534个条目的限制(大小加1存储为无符号的两字节数量),我们得到了65526个构造函数的类文件限制,事实上,我可以使用ASM库生成一个有效的类文件,该库中有那么多构造函数,而不是更多。
实际上,如果你把你的类命名为
java,你可以得到更多。lang.Object
,在这种特殊情况下,没有要声明的超类,也没有要调用的超构造函数。你自己决定,你想拨打的最大电话号码是多少…
如上所述,还有第三个限制,编译器实现。使用Java编译器时,必须确保它不会生成调试信息(在
javac
的情况下,使用-g:none
)以及其他可能占用常量池条目的可选属性。但是使用JDK11的javac
,当您开始定义大量构造函数时,性能将显著下降。我得到了以下编译次数:
1000 constructors: 1 second
2000 constructors: 2 seconds
5000 constructors: 10 seconds
10000 constructors: 1 minute
15000 constructors: 2 minutes
20000 constructors: 4 minutes
30000 constructors: 10 minutes
40000 constructors: 20 minutes
50000 constructors: between 25 minutes and ½ hour
65526 constructors: between 45 minutes and 1 hour
因此,<>代码> javac 最终设法最大化了类文件的限制,但是我们甚至可以在之前考虑实际限制。
Eclipse编译器似乎能更好地处理此类源文件,但由于构造函数数量过多,IDE几乎无法使用。在关闭调试符号并有点耐心的情况下,我成功地用Eclipse编译了一个包含65526个构造函数的类。声明65528构造函数会产生一条关于常量池条目过多的错误消息,而声明65527构造函数会在Eclipse中发现一个错误,生成一个损坏的类文件,声明零个常量池条目(如前所述,该数字存储为count加1,因此编译器供应商必须记住,限制不是65535,而是65534)。
严格来说,JVM类文件格式将一个类的方法数(包括所有构造函数)限制在65536以下。根据Tom Hawtin的说法,有效限值是65527。每个方法签名都占据常量池中的一个插槽。由于65535个池条目中的一些(不可避免地)被其他东西占用,因此格式良好的类文件不可能使用所有可能的方法/构造函数ID。
参考-JVMS 4.1类文件结构
但是,如果您以正常的方式编写合理的Java代码,就不会遇到这种限制。
你应该有多少?这取决于类和用例。拥有多个“便利”构造函数重载,并使用this(…)实现它们通常是很好的
链接到“主”构造函数。(但是,您可以跳过顶部。有N个不同参数的N个可能组合(重载)。)
如果您发现您正在编写过多(主观的!)数量的构造函数,您可能应该看看替代方案,如构建器模式。
在Java中,我们可以在一个类中创建多少构造函数。
我正在使用AWS-CDK为应用程序构建基础设施。 我有一个构建多个S3存储桶的构造和另一个创建lambda函数从这些存储桶获取数据的构造。 为了能够给我的lambda权限从桶中获取数据,我需要桶ARN。 有没有一种方法,我可以从生产桶的结构导出桶arn,并将其导入lambda结构?
我了解到连池的实现是基于提供者的,所以SQL数据提供者的连池工作方式将不同于Oledb的连池。(参考文献:http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx)池的默认最大物理连接是100。如果我们有不同的连接字符串(或不同的字符串顺序,但相同的数据库)或不同的窗口身份(如果我们使用窗口身份验证),新的连接池将被创建。 请让我知道,如果你不清楚
参加以下课程: 由于Foo(std::stringbar_, intbaz_=7);是我唯一的构造函数,编译器不应该为我实现默认构造函数,对吗?我认为我可以构造这个类的唯一两种方法是: 然而,为什么这是可能的? 当唯一的公共构造函数要求其第一个参数具有值时,我不理解如何默认构造类。将默认构造函数设为私有或尝试C 11删除它,没有什么区别。这是怎么发生的 http://ideone.com/CL7I
问题内容: 这是一段代码,作为示例,其余的只是方法(迷宫类的底部)。所以当实例化时,使用 和 这将打印出网格阵列。这是合法的吗?我认为所有类都需要构造函数,它如何打印出二维网格数组? 迷宫课: 问题答案: 不需要 显式 定义构造函数;但是,所有类都必须具有构造函数,如果不提供任何默认构造函数,则将生成默认的空构造函数: 请参见默认构造函数。
问题内容: 这是面试中提出的问题。如果一个类在Java中何时有多个构造函数,我们可以从另一个构造函数调用另一个函数吗? 问题答案: 可以,我知道的语法是 您还可以通过以下方式调用超类的构造函数 这两个调用只能作为构造函数中的第一条语句完成(因此,您只能在执行其他任何操作之前调用另一个构造函数)。