Java 编译器抱怨未处理的IOException,即使函数签名抛出它
我有一个类,其中静态工厂方法使用Java 编译器抱怨未处理的IOException,即使函数签名抛出它,java,Java,我有一个类,其中静态工厂方法使用computeIfAbsent()返回实例: public class TrafficMonitor { private static ConcurrentMap<String, TrafficMonitor> instances = new ConcurrentHashMap<>(); private String busNumber; //private constructor could throw an IOEx
computeIfAbsent()
返回实例:
public class TrafficMonitor {
private static ConcurrentMap<String, TrafficMonitor> instances = new ConcurrentHashMap<>();
private String busNumber;
//private constructor could throw an IOException
private TrafficMonitor(String busNumber) throws IOException {
this.busNumber = busNumber;
// it needs to be in constructor because it call a 3rd party API to instantiate an object which throws IOException
doIoOperation();
}
// static factory method to return a instance of this class
public static TrafficMonitor forBus(String busNumber) throws IOException {
// Compiler error: Unhandled exception: java.io.IOException
return instances.computeIfAbsent(busNumber, TrafficMonitor::new);
}
}
公共类流量监视器{
私有静态ConcurrentMap实例=新ConcurrentHashMap();
专用字符串总线号;
//私有构造函数可能引发IOException
专用流量监视器(字符串busNumber)引发IOException{
this.busNumber=总线号;
//它需要在构造函数中,因为它调用第三方API来实例化抛出IOException的对象
doIoOperation();
}
//返回此类实例的静态工厂方法
公共静态流量监视器forBus(字符串busNumber)引发IOException{
//编译器错误:未处理的异常:java.io.IOException
返回instances.computeIfAbsent(总线号,流量监视器::新建);
}
}
私有构造函数抛出IOException,在静态工厂函数中forBus(String busNumber)
即使我在签名中有抛出IOException
,编译器仍然抱怨未处理的异常:java.io.IOException
。为什么?如何摆脱它
另一个问题:在本例中,
TrafficMonitor::new
是否自动从forBus(字符串busNumber)中获取参数
函数或它如何使用私有构造函数创建实例,该构造函数需要一个参数字符串busNumber
?ComputeFabSent
需要一个函数作为参数。函数SAM的签名是R apply(T)
。如您所见,函数
可能不会引发IOException
。但是您的构造函数确实抛出了一个IOException
。所以TrafficMonitor::new
不是一个函数。因此,您不能将其作为参数传递给computeIfAbsent()
清洁方式:不要在构造函数中执行IO:
public class TrafficMonitor {
private static ConcurrentMap<String, TrafficMonitor> instances = new ConcurrentHashMap<>();
private String busNumber;
private boolean initialized;
private TrafficMonitor(String busNumber) {
this.busNumber = busNumber;
}
private synchronized void initialize() throws IOException {
if (!initialized) {
doIoOperation();
initialized = true;
}
}
public static TrafficMonitor forBus(String busNumber) throws IOException {
TrafficMonitor result = instances.computeIfAbsent(busNumber, TrafficMonitor::new);
result.initialize();
return result;
}
}
或
ComputeFabSent需要一个函数作为参数。函数SAM的签名是R apply(T)
。如您所见,函数可能不会引发IOException。但是你的构造函数确实抛出了一个IOException。所以TrafficMonitor::new不是一个函数。因此,您不能将其作为参数传递给ComputeFabSent()。也许您是对的,我不熟悉双冒号,如何消除它?消除它的干净方法是避免在构造函数中执行IO操作。构造函数不应该这样做。它应该创建一个对象。不太干净的方法是传递一个lambda来调用构造函数,捕获IOException,并将其作为运行时异常重新调用。构造函数不应该这样做
,嗯,没有这样的规则,我认为这取决于具体情况。在我的例子中,这样做是有意义的,因为我的类是第三方API的包装,它在实例化期间抛出IOException
。话虽如此,如果您能为您的答案提供代码示例,那就太好了。SAM
在您的答案中代表什么?单一抽象方法。这是接口必须满足的条件,才能成为功能接口,即能够用作lambda或方法引用的类型。我喜欢干净的方式,但如果仔细查看我的forBus(String busNumber)
,它违反了我试图实现的逻辑,TrafficMonitor
的实例与相同的busNumber
的实例相同。也就是说,它是每个busNumber
的“单例”。只有在创建TrafficMonitor
的新实例时,才应执行doIoOperation()
。您可以修改您的清洁解决方案代码以满足此要求吗?哦,是的,您有一个布尔标志来控制初始化。
private TrafficMonitor(String busNumber) {
this.busNumber = busNumber;
try {
doIoOperation();
} catch(IOException e) {
throw UnchedkIOException(e);
}
}
public static TrafficMonitor forBus(String busNumber) {
return instances.computeIfAbsent(busNumber, busNumber -> {
try {
return new TrafficMonitor(busNumber);
} catch(IOException e) {
throw UnchedkIOException(e);
}
});
}