问题
I've read this: Can I use throws in constructor? -- which gave me the right idea, and led me to one answer, but was not very explicit. I've also read several others, but could not find my answer. To recap what I've learned for context, essentially, this will not compile...
public ExampleClass(String FileName)
{
this(new FileInputStream(FileName));
}
public ExampleClass(FileInputStream FileStream)
{
DoSomethingToSetupBasedUponFileStream(FileStream);
}
...because the FileInputStream
constructor (called from the String Constructor) may throw a FileNotFoundException. You can still create the constructor by making it throw the same exception as follows:
public ExampleClass(String FileName) throws FileNotFoundException
{
this(new FileInputStream(FileName));
}
My question is related to a default constructor (no arguments) that would simply use a default filename String constant:
public ExampleClass() throws FileNotFoundException
{
this(DEFAULT_FILE_NAME);
}
This would chain the constructors as:
ExampleClass()
--> ExampleClass(<String>)
--> ExampleClass(<InputFileStream>)
In a case like this, is it possible to use a default value (static final class member) in the default constructor, to instantiate (further down the chain) a FileInputStream, but not have to use the throws FileNotFoundException
code (which would require someone using the class to either re-throw or handle the exception?
If I could do something like the following, I would handle the exception myself:
public ExampleClass()
{
try
{
this(DEFAULT_FILE_NAME);
}
catch (Exception e)
{
DoSomethingToHandleException(e);
}
}
...However, as far as I know this is not possible, because the "Constructor call must be the first statement in a constructor"
Being more used to .Net at this point, I've never been forced to deal with exceptions if I didn't really want to... :D
回答1:
Refactor your file construction code out of your constructor, so you could do something like this --
public ExampleClass() {
try {
fileInputStreamMethod(DEFAULT_FILE);
}
catch(Exception e) {
...
}
public ExampleClass(String fileName) throws Exception {
fileInputStreamMethod(fileName);
}
private void fileInputStreamMethod(String fileName) throws Exception {
// your file handling methods
}
回答2:
You are correct that you cannot catch an exception from the call to this(...).
You could use a static method to produce what you want:
static ExampleClass createDefault()
{
try
{
return new ExampleClass(DEFAULT_FILE_NAME);
}
catch(Exception e)
{
DoSomethingToHandleException(e)
}
}
回答3:
You could do something like this:
public ExampleClass(String FileName)
{
this(getStream(FileName));
}
private static FileInputStream getStream(String name) {
try {
return new FileInputStream(name);
} catch (Exception e) {
// log error
return null;
}
}
The real question is, why would you not want to throw an exception? How should your program behave if the file cannot be opened? I think it would be unusual that you would want it to proceed as if there were no problem. Quite likely, the null
input stream will cause grief later on.
In general, you're better off throwing an exception as close to the source of an error as possible.
回答4:
Basically what you have to do is do the work that your constructor has to do in a different method(something that's not a constructor) and then use it in the default constructor. But am not sure how useful this technique is in your scenario.
cheers!
来源:https://stackoverflow.com/questions/7125824/chaining-constructors-in-java-without-throwing-exceptions-from-the-default-const