有没有人能给我解释一下这个班级的签名是什么意思-org.apache.logging.log4j.core.appender
Class RollingFileAppender.Builder<B extends RollingFileAppender.Builder<B>>
如文件所示-Log4j2 apidocs
我把它读作Builder
,表示类型B
,其中B
extends
表示类型B* 的 * 生成器,这让我很困惑。
另外,这是一个static
类,它也有一个构造函数。这正常吗?有人能分享一个参考资料,可以帮助我理解和使用这个程序?
PS -关于我在这里做什么-我正在修改log4j代码,使其与log4j 2兼容,其中有一个RollingFileAppender
使用util类中的RollingFileAppender
构造函数创建。
2条答案
按热度按时间pbgvytdp1#
构建器通常有一个流畅的API。也就是说,它们的构建方法返回builder类,以便能够直接调用其他构建方法。例如,有问题的类
RollingFileAppender.Builder
可以这样使用:这意味着构建方法(在本例中以
with
为前缀的方法)必须返回相同的构建器示例。但是...如果你设计了一个被子类化的构建器类,你就有问题了。构建方法应返回什么类型?考虑以下类:
build
方法的实际返回类型与本说明无关。现在的问题是。。您不能执行以下操作:withProperty
的返回类型是Builder
,并且该类型不知道构建方法withChildProperty
。所以你破坏了流畅的API。解决方案:参数化生成器类。下面示例中的类型参数
B
旨在表达 *self类型 * 的概念。对于我们的示例,您执行以下操作:
现在你可以像我上面提到的那样做代码了。
8i9zcol22#
这被称为curiously recurring template pattern。
据我所知,
RollingFileAppender.Builder
没有任何子类,所以从技术上讲,RollingFileAppender.Builder
不需要这样做。它可以被声明为非泛型类型:及其生成器方法,它们都返回
B
(例如,withAdvertise
),也可以返回RollingFileAppender.Builder
。然而,考虑这样一种情况,有人试图编写这个非泛型类的子类:
调用
withFoo
无法编译。这是因为在我们假设的非泛型RollingFileAppender.Builder
中,withAdvertise
返回RollingFileAppender.Builder
,而不是MyBuilder
。将
RollingFileAppender.Builder
设为泛型,并使其生成器方法返回泛型类型参数B
,就可以解决这个问题。因为我们可以这样写:在
RollingFileAppender.Builder
中声明的任何返回B
的方法现在都将返回MyBuilder
。查看
RollingFileAppender.Builder
的继承层次结构也会很有帮助:如您所见,这个类继承了许多构建器方法。如果没有一个类遵循这种奇怪的重复模板模式,那么在使用了从
RollingFileAppender.Builder
的超类继承的方法之后,您将无法调用在RollingFileAppender.Builder
中声明的方法。总而言之,这个
B
只是所有构建器方法返回您正在使用的Builder
子类的一种方式,而不是声明它们的类。虽然RollingFileAppender.Builder
不需要它,因为它没有子类,但作者仍然这样声明它,大概是为了遵循模式。至于为什么
static
类可以有构造函数,static
类只是意味着你不需要外部类(RollingFileAppender
)的示例来示例化嵌套类。它不阻止声明构造函数。