should I use Exception to simulate a goto statement in java - java

I've learned that Exception is slow:
How slow are Java exceptions?
but this article(http://blogs.atlassian.com/2011/05/if_you_use_exceptions_for_path_control_dont_fill_in_the_stac/) says that we can use Exception to simulate a goto statement:
so I think it's ok to write my code like this:
public class MyService {
public Result service(int i) {
Result result = new Result();
try {
Util.checkCommonArguments(i);
//my business logic...
if ((i % 2) != 0) {
throw new BizException("002", "can not be odd");
}
if (i > 200) {
throw new BizException("003", "can not be greater than 200");
}
// the normal processing...
result.setCode("000");
result.setDesc("ok");
} catch (BizException e) {
result.setCode(e.getCode());
result.setDesc(e.getMessage());
} catch (Exception e) {
result.setCode("999");
result.setDesc("system error");
}
return result;
}
}
class Util {
public static void checkCommonArguments(int input) {
if (input < 0) {
throw new BizException("001", "can not be negative.");
}
//maybe more
}
}
class Result {
private String code;
private String desc;
//getter and setter
}
class BizException extends RuntimeException {
private String code;
public BizException(String code, String message) {
super(message);
this.code = code;
}
#Override
public Throwable fillInStackTrace()
{
return this;
}
}
but 'dont fill in the stack trace' does not work:
// throw but catch, but not Filling in exception stack traces
public void method5(int i) {
try {
value = ((value + i) / i) << 1;
// i & 1 is equally fast to calculate as i & 0xFFFFFFF; it is both
// an AND operation between two integers. The size of the number plays
// no role. AND on 32 BIT always ANDs all 32 bits
if ((i & 0x1) == 1) {
throw new MyBizException();
}
} catch (MyBizException e) {
//maybe do something
}
}
method5's cost time is almost the same as:
// This one will regularly throw one
public void method3(int i) throws Exception {
value = ((value + i) / i) << 1;
// i & 1 is equally fast to calculate as i & 0xFFFFFFF; it is both
// an AND operation between two integers. The size of the number plays
// no role. AND on 32 BIT always ANDs all 32 bits
if ((i & 0x1) == 1) {
throw new Exception();
}
}
Now I'm confused. On one side, I want my code clean and clear(like the class 'MyService'). On the other side, Exception is really slow.
Should I use Exception to simulate a goto statement? Thanks.

Don't use exceptions for normal program flow. They are for exceptional circumstances beyond the developer's control. They are slow, inefficient, and designed for error handling, not business logic.
Stimulating a goto is a bad design decision in today's development environment anyways. They are confusing to follow, and difficult to maintain. Refactor your code to use breaks or other control logic instead.

Using exception for flow control is neither in the interest of good design nor efficient. At the very minimum this will create unnecessary objects. I would encourage you to have a look at Joshua Bloch's "Effective Java" which explicitly covers this topic.

Related

display exception in JTextField

My code does some arithmetic to convert a binary input to decimal output. I also made an exception class that extends NumberFormatException to throw an error if the input is not a 1 or 0. What I want is to throw the exception to a JTextField.
private void biTodeciActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
String binary;
binary = binaryStringText.getText();
int total = 0;
for(int i = 0; i < binary.length(); i++)
{
if (binary.charAt(i) != '0' && binary.charAt(i) != '1')
{
throw new ParseMethods.BinaryNumberFormatException(binary.charAt(i)+" is not"
+" a valid binary input.");
}
else if(binary.charAt(i) == '1'){
total += Math.pow(2, (binary.length()-1)-i );
}
}
deciOut.setText(""+total);
}
Essentially, what you're trying to do won't work. The BinaryNumberFormatException doesn't declare that it throws any exceptions (and assuming you're using NetBeans), you won't be able to (easily) modify it.
You could wrap all you code in a try-catch block within the method, but that's just, well, kind of messy (IMHO)
Instead, what I might do, is create a class which does the conversation, something like...
public static class BinaryConverter {
public static String toDecimal(String binary) throws BinaryNumberFormatException {
//...
}
// Maybe a toBinary method as well...
}
for example. The toDecimal declares the fact that it will throw a BinaryNumberFormatException (although I think some kind of parse exception would be better)
Then in your action performed method, you could do something like...
private void biTodeciActionPerformed(java.awt.event.ActionEvent evt) {
try {
deciOut.setText(BinaryConverter.toDecimal(binaryStringText.getText()));
} catch (BinaryNumberFormatException exp) {
exp.printStackTrace();
deciOut.setText(exp.getMessage());
}
}
which would allow to deal with the operation been successful and unsuccessful in a more succinct manner.
This makes the code more reusable and easier to manager.
As an idea
Print exception directly into textfield in STRING format
deciOut.setText(""+exp);

Block I/O in InputStream's read()

I'm trying to write an algorithm, that downloads a video live stream. Specifically, the respective stream I'm trying to fetch is based on a dynamic .m3u8 playlist file, which periodically provides URIs of new video files. The main goal is to combine those individual media files into one coherent InputStream.
I actually succeeded in getting it to work: I periodically check for new media files, that appear inside the playlist, and pass their HTTP streams to a custom InputStream implementation, namely InputStreamChain. Since it's a live stream, I assume it to be endless, at least for the time being. Ergo, I wanted my InputStreamChain's read() never to send the -1. Unfortunately, it did; every time when all queued media streams were consumed, the InputStreamChain ended. Instead, I wanted it to block I/O, until a new media file arrives.
So, I came up with a working solution: I adjusted the read() method to loop until there's a new stream available (a TimerTask will provide the new files). In the loop, I built in a Thread.sleep(), in order to reduce the CPU load:
public int read() throws IOException {
int bit = current.read();
if (bit == -1 && streams.size() > 0) {
// left out due to lacking relevance
} else if(bit == -1 && streams.size() == 0) {
while(streams.size() == 0) {
Thread.currentThread().sleep(50);
}
return read();
}
return bit;
}
Although it seems to work, I have a feeling, that I'm not doing it how I'm supposed to. I also tried using Lock together with Condition.await(), but when my TimerTask tried to trigger Condition.signal(), it just threw a IllegalMonitorStateException.
That's why I'm asking the question:
In what way should I delay/block an InputStream's read() method, especially in my scenario?
Edit:
For the sake of completeness, I'm going to provide my failed Lock approach, too:
private ReentrantLock ioLock;
private Condition ioCond;
private boolean waitingForStream = false;
public InputStreamChain() {
ioLock = new ReentrantLock();
ioCond = ioLock.newCondition();
}
public synchronized InputStreamChain addInputStream(final InputStream stream) {
streams.addLast(stream);
if (current == null) {
current = streams.removeFirst();
}
if(waitingForStream) {
ioCond.signal();
}
return this;
}
public int read() throws IOException {
int bit = current.read();
if (bit == -1 && streams.size() > 0) {
// do stuff
} else if(bit == -1) {
waitingForStream = true;
ioLock.lock();
try {
ioCond.await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
waitingForStream = false;
ioLock.unlock();
}
return read();
}
return bit;
}
Probably you are not using synchronized block. Here is an example:
class MyReader
{
public int read() throws IOException {
int bit = current.read();
if (bit == -1 && streams.size() > 0) {
// left out due to lacking relevance
} else if(bit == -1 && streams.size() == 0) {
waitForNextStream();
return read();
}
return bit;
}
private synchronized void waitForNextStream()
{
// TODO add close handling, set current here
while (streams.isEmpty())
{
wait();
}
}
public synchronized void addNextStream(InputStream is)
{
streams.add(is);
notify();
}
}

Java - Catching multiple exceptions and Identifying which exception occured

I had some difficulty with the title, wasn't sure how to word it more accurately.
I'm having this issue, I have a several methods which ask the user for 3 Double inputs.
For each input it checks if it's valid (for example if its a positive value), if it's not it throws an IllegalArgumentException. Now I made a Tester class to check if the methods are working properly. It's supposed to catch the exception thrown by the methods and re-ask the user for the input which caused that specific exception.
All 3 methods throw and IllegalArgumentException but the error message is different for each one. Is there anyway (when catching the exception) to see which input cause the error? Here's a sample of my code:
public class account
{
double value;
public account(double initialValue)
{
if (initialValue < 0)
{
throw new IllegalArgumentException("Initial value cannot be negative.");
}
value = initialValue;
}
public add(double addValue)
{
if (addValue < 0)
{
throw new IllegalArgumentException("Added value cannot be negative.");
}
value = value + addValue;
}
}
and the tester class would be something like:
public class accountTester
{
public static void main(String[] args)
{
try
{
double initialValue = Double.parseDouble(JOptionPane.showInputDialog("Enter initial value"));
account acc = new account(initialValue);
double addValue = Double.parseDouble(JOptionPane.showInputDialog("Enter value to add"));
acc.add(addValue);
} catch (Exception e) {
System.out.println("Wrong ammount");
initialValue = Double.parseDouble(JOptionPane.showInputDialog("Re-enter ammount"));
}
}
So what would I have to change in the tester class to throw that code only if the IllegalArgumentException is "Initial value cannot be negative."
Sorry if I made this hard to understand.
EDIT: According to my prof, we're supposed to use do
String error = e.toString;
if (error.contains("Added value cannot be negative.")
{
//DO CODE FOR FIRST ERROR
}
I know this isn't the most proper way of doing it though.
Since you can't match over Strings like you would do in a functional language you have to provide three different kind of objects if you want to be able to distinguish them using the try-catch mechanics.
Or with a simplified approach attach a parameter to the exception so that you can use just a catch clause but you could behave differently. Something like
class MyIllegalArgumentException extends IllegalArgumentException {
public int whichParameter;
public MyIllegalArgumentException(String string, int which) {
super(string);
whichParameter = which;
}
}
now you can:
catch (MyIllegalArgumentException e) {
if (e.whichParameter == 0)
..
else if (e.whichParameter == 1)
..
}
You could also check the string for equality but this would be really not a good design choice, you could also have many try-catch blocks but this is not always possible.
After having expanded your code the solution is easy:
public static void main(String[] args) {
try {
double initialValue = ...
account acc = new account(initialValue);
} catch (IllegalArgumentException e) {
...
}
try {
double addValue = ...
acc.add(addValue);
} catch (Exception e) {
System.out.println("Wrong ammount");
initialValue = Double.parseDouble(JOptionPane.showInputDialog("Re-enter ammount"));
}
}
Surround each method call with its own try/catch block?
In your catch block you should only catch IllegalArgumentException. Then what you can do is invoke the getMessage() function which will enable you to do a very simple String.equals call.

Alternatives to embedded if statements?

I have a history in programming, but not much in software development. I'm currently writing a piece of software for the company I work at, and I've come to challenge myself on the readability of my code.
I want to know whether this is a "valid" alternative to embedded if statements, or if there is anything better I could use.
Let's say I have the following method:
public void someMethod()
{
if (some condition)
{
if (some condition 2)
{
if (some condition 3)
{
// ...etc all the way until:
doSomething();
}
else
{
System.err.println("Specific Condition 3 Error");
}
}
else
{
System.err.println("Specific Condition 2 Error");
}
}
else
{
System.err.println("Specific Condition 1 Error");
}
}
Now the first thing I should point out is that in this instance, combining the conditions (with &&) isn't possible, since each one has a unique error that I want to report, and if I combined them I wouldn't be able to do that (or would I?). The second thing I should point out before anyone screams "SWITCH STATEMENT!" at me is that not all of these conditions can be handled by a switch statement; some are Object specific method calls, some are integer comparisons, etc.
That said, is the following a valid way of making the above code more readable, or is there a better way of doing it?
public void someMethod()
{
if (!some condition)
{
System.err.println("Specific Condition 1 Error");
return;
}
if (!some condition 2)
{
System.err.println("Specific Condition 2 Error");
return;
}
if (!some condition 3)
{
System.err.println("Specific Condition 3 Error");
return;
}
doSomething();
}
So basically, instead of checking for conditions and reporting errors in else blocks, we check for the inverse of the condition and return if it is true. The result should be the same, but is there a better way of handling this?
If I was being particularly pedantic I would use something like this.
boolean c1, c2, c3;
public void someMethod() {
boolean ok = true;
String err = "";
if (ok && !(ok &= c1)) {
err = "Specific Condition 1 Error";
}
if (ok && !(ok &= c2)) {
err = "Specific Condition 2 Error";
}
if (ok && !(ok &= c3)) {
err = "Specific Condition 3 Error";
}
if ( ok ) {
doSomething();
} else {
System.out.print(err);
}
}
You are now single-exit AND flat.
Added
If &= is difficult for you, use something like:
if (ok && !c3) {
err = "Specific Condition 3 Error";
ok = false;
}
I would write it as
if (failing condition) {
System.err.println("Specific Condition 1 Error");
} else {
somethingExpensiveCondition2and3Dependon();
if (failing condition 2)
System.err.println("Specific Condition 2 Error");
else if (failing condition 3)
System.err.println("Specific Condition 3 Error");
else
doSomething();
}
yes, your code in both cases smells of conditional complexity (code smells)
Java is an OOP language, so your code should be factored to in the spirit of OOD, something like this:
for (Condition cond : conditions) {
if (cond.happens(params))
cond.getHandler().handle(params);
}
conditions list should be injected to this class, this way when a new condition is added or removed the class doesn't change. (open close principle)
Your second approach is fairly good. If you want something a little more baroque, you can move your conditions into Callable objects. Each object can also be provided with a way of handling errors. This lets you write an arbitrarily long series of tests without sacrificing functionality.
class Test {
private final Callable<Boolean> test;
private final Runnable errorHandler;
public Test(Callable<Boolean> test, Runnable handler) {
this.test = test;
errorHandler = handler;
}
public boolean runTest() {
if (test.call()) {
return true;
}
errorHandler.run();
return false;
}
}
You could then organize your code as follows:
ArrayList<Test> tests;
public void someMethod() {
for (Test test : tests) {
if (!test.runTest()) {
return;
}
}
doSomething();
}
EDIT
Here's a more general version of the above. It should handle almost any case of this type.
public class Condition {
private final Callable<Boolean> test;
private final Runnable passHandler;
private final Runnable failHandler;
public Condition(Callable<Boolean> test,
Runnable passHandler, Runnable failHandler)
{
this.test = test;
this.passHandler = passHandler;
this.failHandler = failHandler;
}
public boolean check() {
if (test.call()) {
if (passHandler != null) {
passHandler.run();
}
return true;
}
if (errorHandler != null) {
errorHandler.run();
}
return false;
}
}
public class ConditionalAction {
private final ArrayList<Condition> conditions;
private final Runnable action;
public ConditionalAction(ArrayList<Condition> conditions,
Runnable action)
{
this.conditions = conditions;
this.action = action;
}
public boolean attemptAction() {
for (Condition condition : conditions) {
if (!condition.check()) {
return false;
}
}
action.run();
return true;
}
}
One might be tempted to add some sort of generic data that could be passed around to share info or collect results. Rather than doing that, I'd recommend implementing such data sharing within the objects that implement the conditions and action, and leave this structure as is.
For this case, that's about as clean as you are going to get it, since you have both custom criteria and custom responses to each condition.
What you are in essence doing is validating some conditions before calling the doSomething() method. I would extract the validation into a separate method.
public void someMethod() {
if (isValid()) {
doSomething();
}
}
private boolean isValid() {
if (!condition1) {
System.err.println("Specific Condition 1 Error");
return false;
}
if (!condition2) {
System.err.println("Specific Condition 2 Error");
return false;
}
if (!condition3) {
System.err.println("Specific Condition 3 Error");
return false;
}
return true;
}
Nope, that's about what you get in Java. If you have too many of these, it may indicate that you should refactor a bit, and possibly even rethink your algorithm -- it may be worthwhile trying to simplify it a bit, because otherwise you're going to come back to the code in a few months and wonder why the heck a + b + c + d = e but a + b' + c + d = zebra
The second option you have is the more readable one. While multiple returns are usually not recommended putting all of them at the beginning of the code is clear (it isn't as if they are scattered all over the method). Nested ifs on the other hand, are hard to follow and understand.

In Java, what is the best way of continuing to call a function until no exception is thrown?

In my Java code, I have a function called getAngle() which sometimes throws a NoAngleException. Is the following code the best way of writing a function that keeps calling getAngle() until no exception is thrown?
public int getAngleBlocking()
{
while(true)
{
int angle;
try
{
angle = getAngle();
return angle;
}
catch(NoAngleException e)
{
}
}
}
Or would it be a better idea to rewrite getAngle() to return NaN upon error?
I'm surprised to read some of the answers to this thread because this scenario is precisely the reason checked exceptions exist. You could do something like:
private final static int MAX_RETRY_COUNT = 5;
//...
int retryCount = 0;
int angle = -1;
while(true)
{
try
{
angle = getAngle();
break;
}
catch(NoAngleException e)
{
if(retryCount > MAX_RETRY_COUNT)
{
throw new RuntimeException("Could not execute getAngle().", e);
}
// log error, warning, etc.
retryCount++;
continue;
}
}
// now you have a valid angle
This is assuming that something outside of the process changed in the meantime. Typically, something like this would be done for reconnecting:
private final static int MAX_RETRY_COUNT = 5;
//...
int retryCount = 0;
Object connection = null;
while(true)
{
try
{
connection = getConnection();
break;
}
catch(ConnectionException e)
{
if(retryCount > MAX_RETRY_COUNT)
{
throw new RuntimeException("Could not execute getConnection().", e);
}
try
{
TimeUnit.SECONDS.sleep(15);
}
catch (InterruptedException ie)
{
Thread.currentThread().interrupt();
// handle appropriately
}
// log error, warning, etc.
retryCount++;
continue;
}
}
// now you have a valid connection
I think you should investigate why getAngle() is throwing an exception and then resolve the problem. If this is random, like input from a sensor, maybe you should wait some time until calling again. You could also make getAngle() blocking, that means getAngle() will wait until a good result is acquired.
Ignoring how you're solving your problem you should have some kind of timeout mechanism, so you don't end up in an endlessloop. This supposes that you don't want to have an possibly infinite loop, of course.
You want to call a method as long as it throws an exception?
This is not programming. You should use the debugger and take a look at the real issue.
And you should never catch an exception without any message or logging!
Could you not have used recursion?
i.e.;
public int getAngleBlocking()
{
int angle;
try
{
angle = getAngle();
return angle;
}
catch(NoAngleException e)
{
return getAngleBlocking();
}
}
}
I would not recommend to do it that way, because when getAngle() never returns a valid value (always throws an exception for some reason) you end up in an endless loop. You should at least define a break condition (e.g. timeout) for this case.
In the end I opted for returning a NaN value, as this prevents careless use of Integer.MIN_VALUE somewhere else.
public float getAngle(boolean blocking)
{
while(true)
{
int dir = getDirection();
if(dir == 0 && !blocking)
return Float.NaN;
else
return (dir - 5) * 30;
}
}
Unless you are using a class that is entirely outside of your control, you really want to reconsider throwing an exception to indicate no angle.
Sometimes, of course, this is not possible either because the class is not yours, or, it is not possible to make dual use of the returned type as both the result or error status.
For example, in your case, assuming all integer (negative and 0) degrees are possible angles, there is no way for you to return an int value that indicates error and is distinct from a valid angle value.
But lets assume your valid angles are in range -360 -> 360 (or equiv. in radians). Then, you really should consider something like:
// assuming this ..
public static final int NO_ANGLE_ERROR = Integer.MIN_VALUE;
// do this
public int getAngleBlocking()
{
int angle;
do {
angle = getAngle();
}while(angle == NO_ANGLE_ERROR);
}
Never use Exceptions to handle flow logic in your code.
as suggested first check why you sometimes get the execption

Categories

Resources