I have the following code:
TestClass test=new TestClass();
test.setSomething1(0); //could, but probably won't throw Exception
test.setSomething2(0); //could, but probably won't throw Exception
I would like to execute: test.setSomething2(0); even if test.setSomething(0) (the line above it) throws an exception. Is there a way to do this OTHER than:
try{
test.setSomething1(0);
}catch(Exception e){
//ignore
}
try{
test.setSomething2(0);
}catch(Exception e){
//ignore
}
I have a lot of test.setSomething's in a row and all of them could throw Exceptions. If they do, I just want to skip that line and move to the next one.
For clarification, I don't care if it throws an Exception, and I can't edit the source code of the code which throws this exception.
THIS IS A CASE WHERE I DON'T CARE ABOUT THE EXCEPTIONS (please don't use universally quantified statements like "you should never ignore Exceptions"). I am setting the values of some Object. When I present the values to a user, I do null checks anyway, so it doesn't actually matter if any of the lines of code execute.
try {
// Your code...
} catch (Exception ignore) { }
Use the word ignore after the Exception keyword.
There is no way to fundamentally ignore a thrown exception. The best that you can do is minimize the boilerplate you need to wrap the exception-throwing code in.
If you are on Java 8, you can use this:
public static void ignoringExc(RunnableExc r) {
try { r.run(); } catch (Exception e) { }
}
#FunctionalInterface public interface RunnableExc { void run() throws Exception; }
Then, and implying static imports, your code becomes
ignoringExc(() -> test.setSomething1(0));
ignoringExc(() -> test.setSomething2(0));
IntelliJ Idea IDE suggests to rename a variable to ignored
when it isn't used.
This is my sample code.
try {
messageText = rs.getString("msg");
errorCode = rs.getInt("error_code");
} catch (SQLException ignored) { }
Unfortunately no, there isn't, and this is by intention. When used correctly, exceptions should not be ignored as they indicate that something didn't work and that you probably shouldn't continue down your normal execution path. Completely ignoring exceptions is an example of the 'Sweep it under the rug' anti-pattern, which is why the language doesn't support doing so easily.
Perhaps you should look at why TestClass.setSomething is throwing exceptions. Is whatever you're trying to 'test' really going to be valid if a bunch of setter methods didn't work correctly?
You can't ignore exception in Java. If a method declares being able to throw something this is because something important can't be done, and the error can't be corrected by the method designer. So if you really wan't to simplify your life encapsulate the method call in some other method like this :
class MyExceptionFreeClass {
public static void setSomething1(TestClass t,int v) {
try {
t.setSomething1(v);
} catch (Exception e) {}
public static void setSomething2(TestClass t,int v) {
try {
t.setSomething2(v);
} catch (Exception e) {}
}
and call it when you need it:
TestClass test=new TestClass();
MyExceptionFreeClass.setSomething1(test,0);
MyExceptionFreeClass.setSomething2(test,0);
You should not ignore Exceptions. You should handle them. If you want to make your test code simple, then add the try-catch block into your functions. The greatest way to ignore exceptions is to prevent them by proper coding.
I know this is old, but I do think there are occasions when you want to ignore an exception. Consider you have a string that contains a delimited set of parts to be parsed. But, this string can sometimes contain say, 6 or 7 or 8 parts. I don't feel that checking the len each time in order to establish an element exists in the array is as straight forward as simply catching the exception and going on. For example, I have a string delimited by '/' character that I want to break apart:
public String processLine(String inLine) {
partsArray = inLine.split("/");
//For brevity, imagine lines here that initialize
//String elems[0-7] = "";
//Now, parts array may contains 6, 7, or 8 elements
//But if less than 8, will throw the exception
try {
elem0 = partsArray[0];
elem1 = partsArray[1];
elem2 = partsArray[2];
elem3 = partsArray[3];
elem4 = partsArray[4];
elem5 = partsArray[5];
elem6 = partsArray[6];
elem7 = partsArray[7];
catch (ArrayIndexOutOfBoundsException ignored) { }
//Just to complete the example, we'll append all the values
//and any values that didn't have parts will still be
//the value we initialized it to, in this case a space.
sb.append(elem0).append(elem1).append(elem2)...append(elem7);
//and return our string of 6, 7, or 8 parts
//And YES, obviously, this is returning pretty much
//the same string, minus the delimiter.
//You would likely do things to those elem values
//and then return the string in a more formatted way.
//But was just to put out an example where
//you really might want to ignore the exception
return sb.toString();
}
Those who write empty catch blocks shall burn in the Hell for the eternity.
Or worse, they will be forced to debug the damn rubbish they wrote forever and ever.
That said, one thing you might want to do is writing exception handling in a less verbose way. The NoException library is very good at that.
Related
I Have a question abouth the code for handling erros made by the user.
So the thing is, I need my user to add a name of a program, to add the memory that program takes in the RAM and to add the time he will have that program open.
I need to add in my code defensive programming, so I thought maybe I could do it by checking if the user actually add the type of the variables that the program need, or if it didn't.
Either way I am confused on how to use the try and catch blocks, for now this is what I have...
System.out.println("add program Id");
String programID = scan.next();
try{
String check;
check = programID;
}catch(Exception e){
System.out.println("add a value of String type");
}
That doesn't work.
anything you can type is a string. I can type '5'. That's a string. You may think it is a number, but this entire block of text is a String, and '5' is in it.
No text is a string too. String x = ""; compiles fine.
Thus, no exception would ever occur here, and it's not clear what scenario you are trying to detect.
Perhaps a programID is of the form: "one capital letter (and only english capitals, not Ü for example), and then up to 3 different digits". For example, 'Z5' or 'Y495'.
You'd need to write code to detect this, no need for try/catch. For example, regular expressions:
private static final Pattern PROGRAM_ID_PATTERN = Pattern.compile("^[A-Z]\\d{1,3}$");
public static void main(String[] args) {
....
String programId;
do {
programId = scanner.next();
if (!PROGRAM_ID_PATTERN.matcher(programId).matches()) {
System.err.println("Enter a valid program ID, e.g. A123");
} else {
break;
}
} while (true);
}
Exceptions are for when a method has multiple different ways to exit.
For example, imagine this method:
byte[] contentsOfFile = Files.readFileFully("myfile.txt");
The readFileFully method seems simple: You provide the name of a file, and it returns a byte array with its contents.
However, that's just one way that could go. What if the file doesn't exist? What if the file exists, but your process doesn't have read access rights? What if the disk is failing or it's a removable drive and it's yanked out halfway through reading it?
These somewhat predictable potential alternate ways out are generally done by exceptions. That method would be throwing FileNotFoundException, noReadAccessException, and more generally IOException, for example.
There's no 'that is not a string' variant of scanner.next().
There is scanner.next(Pattern) which you could use:
private static final Pattern PROGRAM_ID_PATTERN = Pattern.compile("^[A-Z]\\d{1,3}$");
public static void main(String[] args) {
....
String programId;
do {
try {
programId = scanner.next(PROGRAM_ID_PATTERN);
break;
} catch (NoSuchElementException e) {
System.err.println("Enter a valid program ID, e.g. A123");
}
} while (true);
}
The javadoc generally explains what exceptions can occur; if a method doesn't mention any, you're not supposed to try/catch there.
Have a look at the following snippet that tries to convert a list of strings into a list of class objects:
public static List<Class<?>> f1(String... strings) {
return
Stream.of(strings)
.map(s -> {
try {
return Class.forName(s);
}
catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
}
return null;
})
.collect(Collectors.toList());
}
Because of the way Java handles checked exceptions in streams (as has been discussed at length here - where I also blatantly stole my example snippet from), you have to have the additional return statement after the try-catch block. This will result in an unwanted null reference being added to the result of type List<Class>.
To avoid this extra null reference, I came up with the following function, achieving a better result with a plain old procedural loop:
public static List<Class<?>> f2(String... strings) {
List<Class<?>> classes = new ArrayList<>();
for (String s : strings) {
try {
classes.add(Class.forName(s));
}
catch (ClassNotFoundException e) {
// Handle exception here
}
}
return classes;
}
Does this observation allow me to draw a conclusion in the form of a best-practice advice, that could be expressed like the following?
If you need to call a function that throws an exception inside a stream and you cannot make use of stream.parallel(), better use a loop, because:
You'll need the try-catch block anyway (notwithstanding the tricky solutions involving some kind of wrapper around the throwing function provided in the aforementioned discussion)
Your code will not be less concise (mainly because of 1.)
Your loop will not break in case of an exception
What do you think?
You can do this without introducing elements which you have to filter in a subsequent step:
public static List<Class<?>> f1(String... strings) {
return Arrays.stream(strings)
.flatMap(s -> {
try { return Stream.of(Class.forName(s)); }
catch(ClassNotFoundException e) { return null; }
})
.collect(Collectors.toList());
}
Still, this isn’t more concise than a loop solution.
But it should be noted that this has nothing to do with checked exceptions. You want to continue in the exceptional case, omitting the failed element. That always requires you to catch the exception to implement this alternative behavior (the default would be to propagate the exception to the caller), whether the exception is checked or unchecked. The checked case has the advantage of reminding you that you have to do this.
In other words, the Stream API does not allow you to implement the behavior of propagating checked exceptions to the caller in a simple way, but that’s not what you want here anyway. If Class.forName(String) was designed to throw unchecked exceptions only, omitting the try … catch block in map would cause the entire operation to abort in the exceptional case by relaying the exception to the caller. But, as said, that’s not what you want here.
As #Patrick wrote, you could filter your null classes. Just add a filter after the map in your stream:
.filter(Objects::nonNull)
.collect(Collectors.toList());
I am using common FieldSetMapper logic found through searches and in examples on StackOverflow and I have run into a situation which surprised me. Either it is a feature or a bug, but I thought I would present it here for review to see how others handle it.
Using Spring Batch, I have a pipe delimited file which has string and number values which may by optional depending on position. For example:
string|string|number|number|string
string||number||string
In your field set mapper class which implements FieldSetMapper, you usually do some mapping such as:
newThingy.setString1(fieldSet.readString("string1"));
newThingy.setString2(fieldSet.readString("string2"));
newThingy.setValue1(fieldSet.readInt("value1"));
newThingy.setValue2(fieldSet.readInt("value2"));
newThingy.setString3(fieldSet.readString("string3"));
During testing the code for line 1 above worked fine.
For line 2 with the blank values for string2 and value, a Java exception was thrown for the number but not the string:
Caused by: java.lang.NumberFormatException: Unparseable number:
at org.springframework.batch.item.file.transform.DefaultFieldSet.parseNumber(DefaultFieldSet.java:754)
at org.springframework.batch.item.file.transform.DefaultFieldSet.readInt(DefaultFieldSet.java:323)
at org.springframework.batch.item.file.transform.DefaultFieldSet.readInt(DefaultFieldSet.java:335)
at com.healthcloud.batch.mapper.MemberFieldSetMapper.mapFieldSet(MemberFieldSetMapper.java:31)
at com.healthcloud.batch.mapper.MemberFieldSetMapper.mapFieldSet(MemberFieldSetMapper.java:1)
I did some research in the DefaultFieldSetMapper.java class provided by Spring Batch which implements the FieldSet class to try and understand what is going on.
What I found is that the readAndTrim function called by readString returns null if the value read is blank
protected String readAndTrim(int index) {
String value = tokens[index];
if (value != null) {
return value.trim();
}
else {
return null;
}
}
... but when using readInt (and maybe others) we are returning an exception.
private Number parseNumber(String candidate) {
try {
return numberFormat.parse(candidate);
}
catch (ParseException e) {
throw new NumberFormatException("Unparseable number: " + candidate);
}
}
I do see where you can return a default value in some of the methods, but null is obviously not allowed. What I would expect is consistent behavior between all methods in FieldSet implementations which allow one to match the file to my database as the data is read. Blank values in delimited and fixed length files are fairly common.
If number based values cannot be properly handled, I will probably have to convert everything over to String as it is read and then go through the trouble to manual handle the conversion to the database, which obviously defeats the purpose of using Spring Batch.
Am I missing something that I should handle better? I can add more code if needed, I just felt this is commonly used and I could keep this short. Will edit as needed.
Edit: Add info on Unit Tests found for Spring Batch class
The comments in the test case state a default should be set instead, but why? I don't want a default. My database allows a null value in the Integer column. I would have to set the default to some arbitrary number which hopefully no one EVER sends, check for it before insert and then switch to null on insert. I still don't like this "feature."
#Test
public void testReadBlankInt() {
// Trying to parse a blank field as an integer, but without a default
// value should throw a NumberFormatException
try {
fieldSet.readInt(13);
fail();
}
catch (NumberFormatException ex) {
// expected
}
try {
fieldSet.readInt("BlankInput");
fail();
}
catch (NumberFormatException ex) {
// expected
}
}
Always sanity check your input/data. I'll usually throw together a Util class with all the parse/read/verification I need. Bare bones version below...
public static Integer getInteger(FieldSet fs, String key, Integer default) {
if(StringUtils.isNumeric(fs.readString(key))) {
return fs.readInt(key);
} else {
return default;
}
}
Consider the following code:
public Object getClone(Cloneable a) throws TotallyFooException {
if (a == null) {
throw new TotallyFooException();
}
else {
try {
return a.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
//cant be reached, in for syntax
return null;
}
The return null; is necessary since an exception may be caught, however in such a case since we already checked if it was null (and lets assume we know the class we are calling supports cloning) so we know the try statement will never fail.
Is it bad practice to put in the extra return statement at the end just to satisfy the syntax and avoid compile errors (with a comment explaining it will not be reached), or is there a better way to code something like this so that the extra return statement is unnecessary?
A clearer way without an extra return statement is as follows. I wouldn't catch CloneNotSupportedException either, but let it go to the caller.
if (a != null) {
try {
return a.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
throw new TotallyFooException();
It's almost always possible to fiddle with the order to end up with a more straight-forward syntax than what you initially have.
It definitely can be reached. Note that you're only printing the stacktrace in the catch clause.
In the scenario where a != null and there will be an exception, the return null will be reached. You can remove that statement and replace it with throw new TotallyFooException();.
In general*, if null is a valid result of a method (i.e. the user expects it and it means something) then returning it as a signal for "data not found" or exception happened is not a good idea. Otherwise, I don't see any problem why you shouldn't return null.
Take for example the Scanner#ioException method:
Returns the IOException last thrown by this Scanner's underlying Readable. This method returns null if no such exception exists.
In this case, the returned value null has a clear meaning, when I use the method I can be sure that I got null only because there was no such exception and not because the method tried to do something and it failed.
*Note that sometimes you do want to return null even when the meaning is ambiguous. For example the HashMap#get:
A return value of null does not necessarily indicate that the map contains no mapping for the key; it's also possible that the map explicitly maps the key to null. The containsKey operation may be used to distinguish these two cases.
In this case null can indicate that the value null was found and returned, or that the hashmap doesn't contain the requested key.
Is it bad practice to put in the extra return statement at the end just to satisfy the syntax and avoid compile errors (with a comment explaining it will not be reached)
I think return null is bad practice for the terminus of an unreachable branch. It is better to throw a RuntimeException (AssertionError would also be acceptable) as to get to that line something has gone very wrong and the application is in an unknown state.
Most like this is (like above) because the developer has missed something (Objects can be none-null and un-cloneable).
I'd likely not use InternalError unless I'm very very sure that the code is unreachable (for example after a System.exit()) as it is more likely that I make a mistake than the VM.
I'd only use a custom exception (such as TotallyFooException) if getting to that "unreachable line" means the same thing as anywhere else you throw that exception.
You caught the CloneNotSupportedException which means your code can handle it. But after you catch it, you have literally no idea what to do when you reach the end of the function, which implies that you couldn't handle it. So you're right that it is a code smell in this case, and in my view means you should not have caught CloneNotSupportedException.
I would prefer to use Objects.requireNonNull() to check if the Parameter a is not null. So it's clear when you read the code that the parameter should not be null.
And to avoid checked Exceptions I would re throw the CloneNotSupportedException as a RuntimeException.
For both you could add nice text with the intention why this shouldn't happen or be the case.
public Object getClone(Object a) {
Objects.requireNonNull(a);
try {
return a.clone();
} catch (CloneNotSupportedException e) {
throw new IllegalArgumentException(e);
}
}
The examples above are valid and very Java. However, here's how I would address the OP's question on how to handle that return:
public Object getClone(Cloneable a) throws CloneNotSupportedException {
return a.clone();
}
There's no benefit for checking a to see if it is null. It's going to NPE. Printing a stack trace is also not helpful. The stack trace is the same regardless of where it is handled.
There is no benefit to junking up the code with unhelpful null tests and unhelpful exception handling. By removing the junk, the return issue is moot.
(Note that the OP included a bug in the exception handling; this is why the return was needed. The OP would not have gotten wrong the method I propose.)
In this sort of situation I would write
public Object getClone(SomeInterface a) throws TotallyFooException {
// Precondition: "a" should be null or should have a someMethod method that
// does not throw a SomeException.
if (a == null) {
throw new TotallyFooException() ; }
else {
try {
return a.someMethod(); }
catch (SomeException e) {
throw new IllegalArgumentException(e) ; } }
}
Interestingly you say that the "try statement will never fail", but you still took the trouble to write a statement e.printStackTrace(); that you claim will never be executed. Why?
Perhaps your belief is not that firmly held. That is good (in my opinion), since your belief is not based on the code you wrote, but rather on the expectation that your client will not violate the precondition. Better to program public methods defensively.
By the way, your code won't compile for me. You can't call a.clone() even if the type of a is Cloneable. At least Eclipse's compiler says so. Expression a.clone() gives error
The method clone() is undefined for the type Cloneable
What I would do for your specific case is
public Object getClone(PubliclyCloneable a) throws TotallyFooException {
if (a == null) {
throw new TotallyFooException(); }
else {
return a.clone(); }
}
Where PubliclyCloneable is defined by
interface PubliclyCloneable {
public Object clone() ;
}
Or, if you absolutely need the parameter type to be Cloneable, the following at least compiles.
public static Object getClone(Cloneable a) throws TotallyFooException {
// Precondition: "a" should be null or point to an object that can be cloned without
// throwing any checked exception.
if (a == null) {
throw new TotallyFooException(); }
else {
try {
return a.getClass().getMethod("clone").invoke(a) ; }
catch( IllegalAccessException e ) {
throw new AssertionError(null, e) ; }
catch( InvocationTargetException e ) {
Throwable t = e.getTargetException() ;
if( t instanceof Error ) {
// Unchecked exceptions are bubbled
throw (Error) t ; }
else if( t instanceof RuntimeException ) {
// Unchecked exceptions are bubbled
throw (RuntimeException) t ; }
else {
// Checked exceptions indicate a precondition violation.
throw new IllegalArgumentException(t) ; } }
catch( NoSuchMethodException e ) {
throw new AssertionError(null, e) ; } }
}
Is having a return statement just to satisfy syntax bad practice?
As others have mentioned, in your case this does not actually apply.
To answer the question, though, Lint type programs sure haven't figured it out! I have seen two different ones fight it out over this in a switch statement.
switch (var)
{
case A:
break;
default:
return;
break; // Unreachable code. Coding standard violation?
}
One complained that not having the break was a coding standard violation. The other complained that having it was one because it was unreachable code.
I noticed this because two different programmers kept re-checking the code in with the break added then removed then added then removed, depending on which code analyzer they ran that day.
If you end up in this situation, pick one and comment the anomaly, which is the good form you showed yourself. That's the best and most important takeaway.
It isn't 'just to satisfy syntax'. It is a semantic requirement of the language that every code path leads to a return or a throw. This code doesn't comply. If the exception is caught a following return is required.
No 'bad practice' about it, or about satisfying the compiler in general.
In any case, whether syntax or semantic, you don't have any choice about it.
I would rewrite this to have the return at the end. Pseudocode:
if a == null throw ...
// else not needed, if this is reached, a is not null
Object b
try {
b = a.clone
}
catch ...
return b
No one mentioned this yet so here goes:
public static final Object ERROR_OBJECT = ...
//...
public Object getClone(Cloneable a) throws TotallyFooException {
Object ret;
if (a == null)
throw new TotallyFooException();
//no need for else here
try {
ret = a.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
//something went wrong! ERROR_OBJECT could also be null
ret = ERROR_OBJECT;
}
return ret;
}
I dislike return inside try blocks for that very reason.
The return null; is necessary since an exception may be caught,
however in such a case since we already checked if it was null (and
lets assume we know the class we are calling supports cloning) so we
know the try statement will never fail.
If you know details about the inputs involved in a way where you know the try statement can never fail, what is the point of having it? Avoid the try if you know for sure things are always going to succeed (though it is rare that you can be absolutely sure for the whole lifetime of your codebase).
In any case, the compiler unfortunately isn't a mind reader. It sees the function and its inputs, and given the information it has, it needs that return statement at the bottom as you have it.
Is it bad practice to put in the extra return statement at the end
just to satisfy the syntax and avoid compile errors (with a comment
explaining it will not be reached), or is there a better way to code
something like this so that the extra return statement is unnecessary?
Quite the opposite, I'd suggest it's good practice to avoid any compiler warnings, e.g., even if that costs another line of code. Don't worry too much about line count here. Establish the reliability of the function through testing and then move on. Just pretending you could omit the return statement, imagine coming back to that code a year later and then try to decide if that return statement at the bottom is going to cause more confusion than some comment detailing the minutia of why it was omitted because of assumptions you can make about the input parameters. Most likely the return statement is going to be easier to deal with.
That said, specifically about this part:
try {
return a.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
...
//cant be reached, in for syntax
return null;
I think there's something slightly odd with the exception-handling mindset here. You generally want to swallow exceptions at a site where you have something meaningful you can do in response.
You can think of try/catch as a transaction mechanism. try making these changes, if they fail and we branch into the catch block, do this (whatever is in the catch block) in response as part of the rollback and recovery process.
In this case, merely printing a stacktrace and then being forced to return null isn't exactly a transaction/recovery mindset. The code transfers the error-handling responsibility to all the code calling getClone to manually check for failures. You might prefer to catch the CloneNotSupportedException and translate it into another, more meaningful form of exception and throw that, but you don't want to simply swallow the exception and return a null in this case since this is not like a transaction-recovery site.
You'll end up leaking the responsibilities to the callers to manually check and deal with failure that way, when throwing an exception would avoid this.
It's like if you load a file, that's the high-level transaction. You might have a try/catch there. During the process of trying to load a file, you might clone objects. If there's a failure anywhere in this high-level operation (loading the file), you typically want to throw exceptions all the way back to this top-level transaction try/catch block so that you can gracefully recover from a failure in loading a file (whether it's due to an error in cloning or anything else). So we generally don't want to just swallow up an exception in some granular place like this and then return a null, e.g., since that would defeat a lot of the value and purpose of exceptions. Instead we want to propagate exceptions all the way back to a site where we can meaningfully deal with it.
Your example is not ideal to illustrate your question as stated in the last paragraph:
Is it bad practice to put in the extra return statement at the end
just to satisfy the syntax and avoid compile errors (with a comment
explaining it will not be reached), or is there a better way to code
something like this so that the extra return statement is unnecessary?
A better example would be the implementation of clone itself:
public class A implements Cloneable {
public Object clone() {
try {
return super.clone() ;
} catch (CloneNotSupportedException e) {
throw new InternalError(e) ; // vm bug.
}
}
}
Here the catch clause should never be entered. Still the syntax either requires to throw something or return a value. Since returning something does not make sense, an InternalError is used to indicate a severe VM condition.
I would like to parse a JSON, but every time I get a value, I have to put the instruction in a try-catch block. Here is an example:
try {
this.setID(jsonObject.getLong("id"));
} catch (JSONException e) {
}
try {
this.setName(jsonObject.getString("name"));
} catch (JSONException e) {
}
//and so on....
I don't care if an instruction arise an exception. So I was wondering if it is possible to delete all the try-catch blocks and put the instructions all together.
Actually it is more a java problem and not only an android problem....
EDIT
Just clarifying what is the problem.
When an exception arises because there is not the tag I was looking for, I would continue with the next tag check instead of handling the exception. To do this, I have to write the code as I posted above, thus a succession of try-catch blocks. I was looking for a faster (and more elegant) solution.
You can use the opt methods instead of the get methods, assuming that it's okay for the keys not to exist. If the keys are not optional, and your app cannot recover from those fields not all existing, you should definitely use the get methods and fail fast if you run into an error.
Another helpful method you can use is the has() method. This checks if there is a mapping for a given key. (e.g. if (json.has("id") id = json.optString("id"))).
Maybe I didn't understand what you're asking, but why don't you put all calls to jsonObject within the same try-catch block?
try {
this.setID(jsonObject.getLong("id"));
this.setName(jsonObject.getString("name"));
} catch (JSONException e) {
// log or consume it some other way
}
You should never just swallow exceptions. At least log an error.
Like #Sotirios was saying you can't disregard a json exception.
You can put all your json reading in a method and make that method throw the JSONException, like this:
public void readJson(String json) throws JSONException{
this.setID(jsonObject.getLong("id"));
this.setName(jsonObject.getString("name"));
}
but you steel have to do a try catch when you call that method:
try {
readJson(jLine);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I think it is more of a library problem than anything else. A couple of JSON libraries in Java tend to add exceptions in their library calls as if the designer wanted to use invasive C-like error status codes but with the added weight of Java exceptions syntax. I can partially understand the motives for such an interface, but it looks really inelegant.
I would suggest using json-simple, which is too simple sometimes but gets the job done and stays out of the way.
Replace
jsonObject.getFoo("key")
with
jsonObject.optFoo("key")
If the key is not found, a null or similar default value is returned instead of an exception being thrown.
If you want cleaner syntax, you should look at gson. If you know what the json will look like, nothing beats it.
If your JSON looks like this:
{
"id": 432942039,
"name": "My name",
"values": [0, 1, 2, 3]
}
You'd create a POJO class that looks like this:
public class MyClass {
public MyClass() {}
private long id;
private String name;
private int[] values;
}
And parse it like this:
private parse(String jsonString) {
Gson gson = new Gson();
MyClass myObject = gson.fromJson(jsonString, MyClass.class);
}
And that's it. No setters are needed; it uses reflection to match the fields. No annotations. No errors if there are fields in your JSON string that don't match anything in your POJO and vice versa.