我正在使用构造函数链接,我担心这会导致资源泄漏。下面是我的两个构造器:
/**
* Constructor to build the map based off of a file. Redirects to the Scanner-based constructor
* @param fileName the name of the file to open
*/
public GeoMap(String fileName) throws FileNotFoundException {
this(new Scanner(new File(fileName)));
}
/**
* Constructor to build the map based off of a Scanner. (Probably from an open file.)
* @param scanner the Scanner to read
*/
public GeoMap(Scanner scanner) {
// goes on to read the string data and make an object...
从任何类型的 Scanner
(键盘、文件等),尽管它通常来自一个文件。问题是,我认为这里正在发生资源泄漏。每当我在读一个文件时,我喜欢在完成后关闭它。问题是,构造函数链接意味着 this()
呼叫必须在第一行。我倾向于这样做:
this(Scanner scannerToClose = new Scanner(new File(fileName)));
在我的脑海里,那会给我一个 Scanner
然后我就可以结束了。但这似乎真的把编译器搞糊涂了——我从中得到了大约5个编译时错误,包括很多“找不到符号”的问题,这些问题意味着编译器不适合这种类型的东西。java支持这个吗?或者我需要做出完全不同的决定 initFromScanner()
两个构造函数都调用的函数(不优雅。)
谢谢。
4条答案
按热度按时间0ejtzxu11#
让我们从这个开始:
这里有资源泄漏吗?好吧,这取决于关店的责任在哪里
Scanner
谎言。如果责任在施工人员,那么我们可以这样堵住漏洞:
这是理想的解决方案,但它假定
Scanner
是构造函数。如果是来电者的责任,那么来电者需要处理防漏。这是可行的。。。但超出了这个问题的范围。
如果这既不是构造函数的责任,也不是调用者的责任,那么您需要处理
GeoMap
它本身就是一种资源,以及它所包含的一切。现在我们考虑一下:
首先,你知道吗
new Scanner(new File(fileName))
是否存在潜在的资源泄漏?理论上,是的。这个
Scanner
构造函数可以为文件打开一个流,然后失败,使流保持打开状态。实际上,这种可能性很小。如果我们忽略类库中的错误,以及应用程序错误,比如使用无法识别的字符集名称,那么
new Scanner
如果你有oome的话,可能会泄露文件描述符。但无论如何,这很可能触发一个完整的gc。那之后呢?
答案取决于先前关于责任在哪里的答案
GeoMap(Scanner)
建造师。如果责任在施工人员,我们知道如何避免泄漏;见上文。
否则。。。我们有问题:
有可能的解决办法,但它们可能涉及改变
Scanner
已使用。也可能存在涉及直接使用该构造函数的泄漏。
总之,这取决于您如何指定和实现
GeoMap(Scanner)
,的GeoMap(String)
构造函数可以在实践中实现防漏。5w9g7ksd2#
在geomap(scanner)构造函数的末尾调用scanner.close()。
这将关闭在geomap(字符串文件名)中创建的扫描器,因为对它的引用作为扫描器传递到geomap(扫描器)中。
实际上,scanner变量指向已创建的新扫描仪,因此在任何方法中的任何位置调用scanner.close()都会关闭它可能在其范围内的任何和所有其他方法。
下面是一个演示扫描仪面向对象特性的程序:
输入.txt:
Smitty
输出:本质上,扫描仪创建在哪里并不重要,如果它在任何一点关闭,那么它在范围内的任何地方都是关闭的。
xpszyzbs3#
我假设您的问题是,您只想关闭涉及的扫描仪,如果您已经在您的构造函数中创建了它
fileName
. 我不认为你的想法有什么问题init
两个构造函数都调用的方法。我不认为那是不雅的。我想我要做的是创建第三个私有构造函数,而不是
init
方法。这两种方法都是一样的,尽管在某个时候你可能希望能够传入一个预构建的扫描程序,在构造函数调用结束时关闭它,在这种情况下,你可以公开这个新的构造函数,这样你就可以从外部调用它了。在这两种情况下,我要做的是将一个布尔“closescanner”参数传递给新的构造函数/方法,以指示是否应该关闭扫描仪。以下是我在代码中的想法:
xmd2e60i4#
首先,你们班
GeoMap
应该定义它如何处理构造函数中提供给它的扫描器;通常,当它被允许创建自己的Scanner
在您的示例中,策略是GeoMap
示例可以对扫描器做任何它想做的事情,包括关闭它——这意味着它拥有它,并且所有权在相应的构造函数中转移。如果不是这样(它不拥有扫描仪),您要么放弃
GeoMap(String)
构造函数(因为GeoMap
示例拥有它,还有谁会拥有它并在以后处理它?),或者您必须使用类似于下面的设计:在这里,所有权由标志跟踪
m_MayCloseScanner
. 不幸的是,这还不能解决您的资源泄漏问题:当GeoMap
示例不再使用。当你的
GeoMap
示例将根本不拥有扫描仪,您不在乎,扫描仪占用的资源是一个便便(其他人的问题)。好的,当您只需要扫描仪来初始化
GeoMap
例如,你可以有一个init()
完成后关闭扫描仪的方法:当然,什么时候
GeoMap
可能拥有也可能不拥有扫描仪,闭合线需要如下所示:if( m_MayCloseScanner ) m_Scanner.close;
.但如果init选项不起作用,则需要一个
GeoMap
示例。析构函数的概念在java中并不存在,最接近它的是实现finalize()
,但这在一段时间前被否决了(最后是Java9),这是有充分理由的。看看这篇关于如何使用
Cleaner
,PhantomReference
以及Closeable
为了你的GeoMap
班级。一开始看起来有点混乱,但最后却显得相对直截了当。