【发布时间】:2020-04-01 12:20:06
【问题描述】:
下面的代码块
package com.example;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Test {
private static final Logger LOGGER = LogManager.getLogger(Test.class);
public static void main(String[] args) {
try {
log("1234", "main", "try");
} catch (Exception e) {
log("main", "Error in main",e);
}
}
static void log(String methodName, Object message, Throwable t) {
LOGGER.error("[Method Name :" + methodName + "] [Message :" + message + "]", t);
}
static void log(String requestId, String method, Object message) {
LOGGER.error("[RequestId :" + requestId + "]" + "[Method Name :" + method + "] [Message :" + message + "]");
}
}
在catch 块声明中给出方法调用错误
错误:对日志的引用不明确 log("main", "main 中的错误",e); ^ Test 中的方法 log(String,Object,Throwable) 和 Test 中的方法 log(String,String,Object) 都匹配
我无法理解。我在这里遇到了很多问题,但其中大多数都涉及可变参数或泛型。虽然无法确定上述代码有什么问题。 通过 JSL 无法确定我违反了什么规则。任何有助于理解这一点都会很棒。
我知道一些讨论过的问题
重命名方法
参数的显式类型转换
作为解决方案,让编译器清楚地知道要拾取哪种方法。但我很期待了解为什么重载的方法在这里不起作用。此外,如果将第二个参数类型转换为Object,代码可以正常工作,但为什么呢?
有些问题确实提到了在 Java 8 中比 7 改进的类型推断,所以为了澄清我在 Java 8 上运行它。
【问题讨论】:
-
由于 String 和 Throwable 从 Object 继承,编译器无法确定使用哪个方法,因为两者都匹配。为什么要让
message成为一个对象?我认为您应该删除Object作为参数类型的任何使用并改用具体类型,这将使如何使用这些方法更加清晰和容易理解,编译器会很高兴 -
不是问题的答案,但 slf4j 不会遇到这样的问题。
-
@JoakimDanielson 我已经添加了代码作为演示来传达这个想法。我正在围绕记录器编写一个包装器,以便可以隐藏实际实现,并且还可以记录我必须添加的更多参数。通常,对于日志记录位,我更愿意将其声明为
Object,因为它可以灵活地记录任何内容或不必每次都显式调用toString -
几乎每个看到 log 方法的人都希望使用名为
message的参数的参数是 String 类型,所以对我来说,你的解决方案只是令人困惑。如果有的话,您应该有类似customObject、extraInfo或类似 Object 类型的东西,可以补充 message 参数。 -
是的,我明白了,但从当前的实现开始,我计划使用 Log4J,它允许 Object 作为参数,因此试图保持与此相似。我知道 Log4J 参数,但后来开始考虑围绕
log(Object message)的包装器。