Related
This is my first time posting a question so I apologize if I am vague or unclear. I'm still learning some of the essentials of Java and I came across a tutorial online regarding exceptions. The entire thing can be found here: Java World: Exceptions in Java.
This may be a dumb question but I'm having difficulty understanding it.
class VirtualCafe {
public static void serveCustomer(VirtualPerson cust,
CoffeeCup cup) {
try {
cust.drinkCoffee(cup);
System.out.println("Coffee tastes just right.");
}
catch (UnusualTasteException e) {
System.out.println(
"Customer is complaining of an unusual taste.");
String s = e.getMessage();
if (s != null) {
System.out.println(s);
}
// Deal with an unhappy customer...
}
}
}
I'm having trouble understanding why would you want to store a string object and then have it print if the previous println seemed like it took care of the problem. What exactly does the second println print out? drinkCoffee() throws a few types of Exceptions including UnusualTasteException. I'd appreciate any feedback!
Here's the code for UnusualTasteExpection:
class UnusualTasteException extends Exception {
UnusualTasteException() { }
UnusualTasteException(String msg) {
super(msg);
}
}
To give an example, if the exception is thrown like this:
throw new UnusualTasteException("The coffee is very bitter");
the println() you're asking about would print out The coffee is very bitter, which is more informative than the generic "unusual taste" message.
This code (sort of) highlights a couple of things:
Catching exceptions and getting meaningful information from them
Dealing with null when it's undesirable to allow around
So, let's be explicit - the code in the catch block is dealing with whatever error message we bring back from the drinkCoffee method thrown by the UnusualTasteException. That said, we print a more generic message about the fact that the customer had an unusual taste with their coffee.
The second println concerns if we had anything meaningful to learn from the exception; a message or a clue or something. It could also be the case that someone passed in null to the constructor in this manner:
throw new UnusualTasteException((String) null);
...or more innocuously:
String msg = null;
throw new UnusualTasteException(msg);
If we don't have anything meaningful to print out, then we don't print it out. We also want to avoid repeated calls to the method, so we store the result of the call into a variable. This is what the second block accomplishes.
As a general aside, this is considered using exceptions as flow control, because there are any number of ways to handle this scenario appropriately (an enum for satisfaction of taste, or a boolean for whether they liked it or not stored on the drinker). In general, it's considered poor practice because exceptions are incredibly expensive to generate, and should be reserved for something truly exceptional.
So your code (within drinkCoffee method) would be doing something like to throw an exception:
throw new UnusualTasteException ("Weird coffee taste!!!");
If you see Exception class's parent i.e. Throwable has a field called detailMessage and then when you call above constructor to throw an exception, it will set detailMessage field.
And that's what you are using in your second print statement. So your print statement would print "Weird coffee taste!!!"
By doing so, you get exact string and intention of exception. And you might be throwing same exception from tea, lemon etc. but if you were processing flow for coffee, you see that it was weird taste of coffee and not lemon or tea and so on.
Let say you have a method that checks if the argument (Answer) is correct and check if the question already have answers in the list that is also correct:
public void addAnswer(Answer answer) {
if (answer.isCorrect()) {
...
}
}
However, I only want one answer to be correct in the list. I have multiple options. I could throw an exception, I could ignore it, I could return some boolean value from the addAnswer that tells me if the operation was ok or not. How are you supposed to think in such scenarios?
The rule is pretty simple: Use exceptions on exceptional, erroneous, unpredicted failures. Don't use exceptions when you expect something to happen or when something happens really often.
In your case it's not an error or something truly rare that an answer is not correct. It's part of your business logic. You can throw an exception, but only as part of some validation (assertion) if you expect an answer at given point to always be correct and suddenly it's not (precondition failure).
And of course if some failure occurs while checking correctness (database connection lost, wrong array index) exception are desired.
This entirely depends on what you want to achieve. Should the caller of your method already have made sure that it doesn't add two correct answers? Is it a sign of a programming error if that happens? Then throw an exception, but definitely an unchecked exception.
If your method's purpose is to relieve the caller from enforcing the one-true-answer invariant (I doubt that, though), then you can just arrange to signal via a boolean return value, which makes it only an optional information channel for the caller.
If there is no way to know in advance whether there are other correct answers—for example, the answers are added concurrently from several threads or even processes (via a database)—then it would be meaningful to throw a checked exception.
Bottom line: there is no one-size-fits-all best practice, but there is a best practice for every scenario you want to accomplish.
The exception police will be down on you like a ton of bricks, and me for this answer, with statements like "don't use exceptions for flow control" and "don't use exceptions for normal conditions".
The trouble with the first statement is that exceptions are a form of flow control. This makes the argument self-contradictory, and therefore invalid.
The trouble with the second statement is that it seems to inevitably go along with endlessly redefining exceptional conditions as normal. You will find examples in this very site: for example, a lively discussion where the police insisted that EOF was 'normal' and therefore that EOFException shouldn't be caught, despite the existence of dozens of Java APIs that don't give you any choice in the matter. Travel far enough down this path and you can end up with nothing that is exceptional whatsoever, and therefore no occasion to use them at all.
These are not logical arguments. These are unexamined dogmas.
The original and real point, back in about 1989 when it was first formulated, was that you shouldn't throw exceptions to yourself, to be handled in the same method: in other words, don't treat it as a GOTO. This principle continues to have validity.
The point about checked exceptions is that you force the caller to do something about handling them. If you believe, on your own analysis, that this is what you want, use an exception. Or, if you are using an API that forces you to catch them, catch them, at the appropriate level (whatever that is: left as an exercise for the reader).
In other words, like most things in the real world, it is up to your discretion and judgment. The feature is there to be used, or abused, like anything else.
#Exception police: you will find me in the telephone book. But be prepared for an argument.
An exception thrown from a method enforces the callers to take some action in the anticipation of the exception occurring for some inputs. A return value doesn't enforce the same and so it is up to the caller to capture it and take some action.
If you want the callers to handle the scenario to take some corrective action, then you should throw a checked exception (sub class of java.lang.Exception).
The problem here is that your API is error prone. I'd use the following scheme instead:
public class Question {
private List<Answer> answers;
private int mCorrect;
// you may want a List implementation without duplicates
public void setAnswers(List<Answer> answers, int correct) {
this.answers = answers;
// check if int is between bounds
mCorrect = correct;
}
public boolean isCorrect(Answer answer) {
return answers.indexOf(answer) == mCorrect;
}
}
because an Answer by itself is simply a statement, and usually cannot be true of false without being associated to a Question. This API makes it impossible to have zero or more than one correct answers, and forces the user to supply the correct one when he adds answers, so your program is always in a consistent state and simply can't fail.
Before deciding how to signal errors, it's always better to design the API so that errors are less common as possible. With your current implementation, you have to make checks on your side, and the client programmer must check on his side as well. With the suggested design no check is needed, and you'll have correct, concise and fluent code on both sides.
Regarding when to use a boolean and when to use Exceptions, I often see boolean used to mirror the underlying API (mostly low level C-code).
I agree with Tomasz Nurkiewicz's response. I cant comment on it because I'm a new user. I would also recommend that if the addAnswer() method is not always going to add the answer (because they already exists a correct one), name it to suggest this behaviour. "add" is suggest normal collections behaviour.
public boolean submitAnswer(Answer answer); // returns true is answer accepted
Your exact solution may depend on the bigger picture about your application that we dont know about. Maybe you do want to throw an Exception but also make it the responsibility of the caller to check if adding the Answer is valid.
It's all a rich tapestry.
I would implement it in this way:
public class Question {
private int questionId;
private final Set<Answer> options = new HashSet<Answer>();
private final Set<Answer> correctAnswers = new HashSet<Answer>();
public boolean addAnswer(Answer answer) throws WrongAnswerForThisQuestionException {
if(!answer.isValid(questionId)) {
throw new WrongAnswerForThisQuestionException(answer, this);
}
if (answer.isCorrect(questionId)) {
correctAnswers.add(answer);
}
return options.add(answer);
}
}
I am trying to check whether the value passed by an user is valid constant or not. Here is the code I have written.
enum Media_Delivery {
Streaming, Progressive
}
public class TestMain {
public static void main(String[] args) {
String medi_delivery = "streaming";
try {
Media_Delivery.valueOf("streaming");
} catch (IllegalArgumentException e) {
System.out.print(e);
}
}
}
Now, in above code if the String passed is not withing the listed enum then it throws IllegalArgumentException which is obvious.
But my question is: Is this the proper way to validate? As we are using Java's exception mechanism to validate.
Can someone suggest a better idea or what I have coded above itself is the best option ?
-----EDIT--------
Another case which I wanted to discuss:
public class TestMain {
public static void main(String[] args) {
String inputPassed = "2a";
try {
Integer.parseInt(inputPassed);
} catch (NumberFormatException nfe) {
throw new SomeUserDefinedException("Please enter only numeric values");
}
}
So is this a good idea ? Or there should be our own parsing mechanism?
Exceptions should be used for exceptional conditions; things you don't expect to happen. Validating input isn't very exceptional.
Josh Bloch actually outlines this specifically in his book 'Effective Java' which IMHO is something every Java programmer should have.
EDIT: And this is actually a very good answer to how to approach the problem:
Check valid enum values before using enum
It is usually best practice not to catch or throw unchecked expressions (IllegalArgumentException is a RuntimeException which counts as "unchecked"). See the Java Tutorials - Exceptions for more details. If you can avoid it, try rewriting your code such that a runtime exception is not needed to be caught. This is a controversial issue, but runtime exceptions exist for a reason: they help the programmer identify bugs. If you catch them, then the bug is not being fixed, it is just being avoided. Try using an if-else statement?
According to the API, "the name must match exactly an identifier used to declare an enum constant." I believe this means the parameter is case-sensitive. In addition, the return type of the valueOf method is some type, not void, so you can't have that statement in the try block. try blocks should contain commands or void methods, such as int x = 3; or System.out.println(3); or something.
--------EDIT-------
OP, in response to your comment:
Like others here have said, it depends on what you're trying to accomplish. I assume that since you have the line Media_Delivery.valueOf("streaming"); in the try block, that you're attempting to see whether "streaming" is equal to one of the enum constants? In that case, you wouldn't need an if-else statement, you could simply write
boolean result = medi_delivery.equals(Media_Delivery.Streaming.name()) ||
medi_delivery.equals(Media_Delivery.Progressive.name());
System.out.println(result);
Or even better, if you don't want to have multiple || conditions, try a switch statement that cycles through each enum constant, testing the equality of the given string.
-Chris
PS: on naming convention, since enum constants are implicitly static final, it is common practice to declare them in all caps, such as STREAMING and PROGRESSIVE (the Java Tutorials - Enums).
I'd say it depends.
If input comes from GUI element like combobox or anything, where enum values are the only ones to choose - then your approach is ok. Here different value would really be an exception.
But if you're making console app, or textfiled with possibility to type anything then result different then enum values shouldn't be considered as exception. You should use normal if-else or cases with this approach.
generally: use exceptions only for exceptional cases, and not for something that is really likeable to happen.
There is no single "proper" way to validate, what you have would certainly be the way I would validate, but there are other ways(for instance you could put all the valid string values of the enumeration in a HashSet and then check against that set to see if its valid, that is probably what the valueOf method does anyway)
Now if the above approach is any "better" or not, that too is to be pretty subjective. If you are doing the validations in a loop and want to reject anything that contains invalid data, then the exception approach is probably best. If you want to flag all the inappropriate elements then either approach works.... the HashSet will probably be faster if there is a lot of problematic data as you wont have to generate a lot of new exception objects, but even then the difference in performance will be pretty negligible.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
I was going through Questions every good .Net developer should be able to answer and was highly impressed with the content and approach of this question, and so in the same spirit, I am asking this question for Java/Java EE Developer.
What questions do you think should a good Java/Java EE programmer be able to answer?
I am marking this question as community wiki as it is not user specific and it aims to serve programming community at large.
Looking forward for some amazing responses.
EDIT: Please answer questions too, as suggested in the comments, so that people could learn something new regarding the language, too.
What is the relationship between hashCode() and equals()? What is the significance of these methods? What are the requirements for implementing them?
What is the difference between Set, Map and List?
I'm still amazed how many people don't know this one in a telephone interview.
Can an interface extend multiple
interfaces?
Most people answer "no", because they know java doesn't have multiple inheritance. But an interface can still extend multiple interfaces (but a class can't extend multiple classes). This doesn't lead to the diamond problem.
If the answer is "no", the interviewer should ask "why would it be forbidden?". Then you start thinking about it and you should realize that there is not problem with it.
So you learned something (by yourself) in the interview and you showed the interviewer that you are able to reason about classes, objects, inheritance, polymorphism, etc. It's actually much better than a candidate who knows the answer by heart but doesn't understand why
Usage of final keyword in method calls.
For example why does the method test in below code does not give any compile error despite using final qualifier for the method parameter.
class Name {
private String name;
public Name (String s) {
this.name = s;
}
public void setName(String s) {
this.name = s;
}
}
private void test (final Name n) {
n.setName("test");
}
One sure is comparison of string. Difference between
String helloWorld = "Hello World";
helloWorld == "Hello World";
"Hello World".equals(helloWorld);
Trick question: What kinds of parameters are passed by reference in Java?
It's amazing how many people still parrot the "primitives are passed by value, objects are passed by reference" mantra.
You said "Good","Developer". Here are my 2 cents too.. :)
What does a "checked exception" mean?
Which one is better to use and when: Assertions or Exceptions to handle unexpected conditions?
Why String class is final? (or is it not? ;) )
are the wait, notify and notifyAll methods in Object class?
Why isn't Thread class final? Why would I extend Thread, ever?
Why there are two Date classes; one in java.util package and another in java.sql?
What happens if an exception is thrown in finally block? Is the remaining finally executed or not?
There is a garbage collector alright, but then is memory leak totally absent in a Java applications? If not, how so?
For J2EE:
Is it good to have instance/static variables in a servlet? Why not? Then where do you store "state"?
continuing on above question: what & where is a "state" for a (web) application?
What happens if I started creating/closing DB connections in "JSP"?
What are the ways to handle JSP exceptions? try-catch? Hmmm.. is there anything else?
I can think many, many, many more of 'em but this'll do for now :)
What is difference between String, StringBuffer and StringBuilder?
"What's a deployment descriptor?"
If the candidate shudders involountarily, he has experience working with pre-3.0 EJBs.
Many questions and interviews are available at http://www.techinterviews.com/interview-questions/java and I don't really see value in copy / pasting a selection of them.
No, it's up to you to create your own compilation of things you think are important. Personally, I proceed always in two steps: first a few questions to get a basic idea of the experience and skills, then a problem solving situation. I'm indeed not convinced that being able to answer any known questions makes you a good or bad unknown problems solver. So, I prefer to ask people to solve a given problem, to give them some requirements, and ask them to write code (but not on paper). I give them some time to come back to me and check how they did it, their coding style, how they used the suggested APIs, etc.
That all being said, my favorite question is "what don't you like about Java?" (in the spirit of this one). It is really a excellent question, it gives you an immediate feedback on how much a candidate has used Java and explored its API and if he just religious about it or not (as the OP wrote).
Update: As suggested by CPerkins, a better wording for the question suggested above might be "What would you most like to see changed in Java?". And indeed, I prefer this way.
What is 'System', 'out', 'println' in System.out.println ?
What happens when you call 'put' on HashMap ?
Explain the various access modifiers used in Java. I have had lots of people struggle with this, especially default access.
If you could change one thing about the Java language or platform what would it be? Good developers will have an answer here while those who aren't really interested in development probably don't care.
If their CV says something like they use EJB2.1 then ask about EJB3 to see what they know about it. The best developers will keep up with the latest developments even if they don't use the newer versions.
What is the general contract when overriding equals?
Is better option prefer lists or arrays?
What are the generally accepted naming conventions?
How serialization works?
How to implement Comparable?
What are the advantages of using JDBC's Prepared Statements?
What is Java EE?
What is a container and what services does it provide?
If you are hiring graduates with Java "experience" a simple question like Write some code that will cause a NullPointerException to be thrown can distinguish which candidates have used Java recently, and didn't just stop when they finished their unit/course.
What will be printed?
public void testFinally(){
System.out.println(setOne().toString());
}
protected StringBuilder setOne(){
StringBuilder builder=new StringBuilder();
try{
builder.append("Cool");
return builder.append("Return");
}finally{
builder.append("+1");
}
}
Answer: CoolReturn+1
A bit more difficult:
public void testFinally(){
System.out.println(setOne().toString());
}
protected StringBuilder setOne(){
StringBuilder builder=new StringBuilder();
try{
builder.append("Cool");
return builder.append("Return");
}finally{
builder=null; /* ;) */
}
}
Answer: CoolReturn
What is the difference between an abstract class and an interface? When would you use each of them?
Lots of Java developers don't know this, I asked most people on my computer science course at university and the vast majority could not answer it.
Simple questions such as,
What is JRE and JDK?
Why does java claim interoperability?
Though these are very basic, many developers do not know the answers. I suggest these be asked before the code-related queries.
Top 5 J2EE/JEE questions
The list of J2EE/JEE middleware questions I have faced is exceptionally long, but here are the top 5 that I have been asked, and have lead to good discussions:
What happens when an MDB encounters an exception that it cannot handle?
This question usually leads to various interesting discussions about poison messages, error queues, etc.,
Given a JMS Topic, and a few consumers on different JVMs, questions on various scenarios with and without durable consumers.
This question usually allows me to discuss in terms of when to use durable subscribers, when to use queues, etc.,
If stuck in a situation where accessing a Hibernate/JPA POJO contents leads to exceptions, how would one resolve it?
This leads to wonderful discussions about lazy loading, rehydrating, etc., It has even lead to comparing and contrasting JPA with Entity beans. I have found it useful to be prepared, and to be clear in concepts.
How could a simple web service be provided?
Any solution from simple web server based to sophisticated SOAP/REST solutions, and any in between, should be good enough. Also, based on the interviewer, sometimes it leads to very interesting discussions on topics such as some design ideas - WSDL first, doc-style, SOAP intermediaries, etc., It might lead to questions such as listing improvements in JAX-WS over JAX-RPC, or SOAP1.2 over SOAP1.1, answers to which are usually based on how much I remember.
JEE 5 resource injection
This question is posed in many ways, starting from Service Locator pattern to javax.naming.Context questions.
Another tricky question I find troubling, but have faced many times is,
How are dependent libraries packaged into an archive?
or Visibility of various classes in a bundled archive.
If the discussion does not lead to class loader hierarchy of different application servers, resource archives, etc., it is best to resign and move on.
Top 5 core Java questions:
Questions on java.util.collections
This is the mother of all questions. Once you can effectively land the interviewer in this area, and if you are prepared, the rest of the interview usually stays here. Be sure of knowing Set, List, Map, and the importance of Object.equals() and Object.hashCode() in every implementation of these interfaces.
Refactoring questions
These are good if the interviewer has an open mind. If the interviewer already has a specific solution in mind, and yours does not match his/hers, you are pretty much doomed. It is best to agree with the answer "I understand other solutions are possible. "
Questions on multi-threading in JDK5, comparing with earlier JDK versions
I have found it is best to be prepared with java.util.concurrent package classes. Doug Lea's book has most of the answers.
What's new in JDK1.6/JDK1.7...?
This is a sure shot question with many interviewers. As much as I hate this, it is best to be prepared. At least remembering a few that I have worked with, and leading the discussion in some other direction, largely and effectively dodges and solves the problem.
Patterns in Java API
Time and again I have been asked to point out a GoF pattern in the Java API. Better be prepared for this one.
Difference between and web server and a web container
What do you like most / least about Java and why?
why would you override the toString() method?
A more pure Java question:
What is the difference between sleep and wait ? Not many people actually understand how wait is working.
How do you need to handle InterruptedExceptions ?
This is the question I faced in my interview.
Why is main method in Java called as public static void main(String[] args) ?
Answer:
1.main() must be declared public because it is invoked by JVM whenever the program execution starts.JVM doesnot belong to our program package.
Inorder to access main outside the package we have to declare it as public.If we declare it as anything other than public it shows a Runtime Error but not Compilation time error
2.main() must be declared as static because if a method is declared as static then we can call that method outside the class using ClassName.methodName();
class Sample
{
static void fun()
{
System.out.println("Hello");
}
}
class Test
{
public static void main(String[] args)
{
Sample.fun();
}
}
The JVM will first Load the Test class,and will check for the Commandline arguments and calls the main method as Test.main();
3.main() must be declared as void main() because JVM is not expecting any value from main().So,it must be declared as void.
If other return type is provided,the it is a RunTimeError i.e;NoSuchMethodFoundError.
4.main() must have String arguements as arrays because JVM calls main method by passing command line arguement.As they are stored in string array object it is passed as an argument to main().
What is the difference between J2SE and J2EE (or JSE and JEE)?
A developer should be able to point out that the enterprise edition is basically an interface definition (i.e. a specification) which can be implemented by vendors. Whereas the standard edition is an implementation in its own right
How does volatile affect code optimization by compiler?
How about what is a session bean and describe some differences between stateless and stateful session beans.
Write a program to accept two integers and output the largest of two numbers to a file at a location of your choice. Now describe what each statement does.
It's possible to drill down pretty deep starting from the significance of the import statement, right down to abnormal termination
Core:
1. What are checked and unchecked exceptions ?
2. While adding new exception in code what type (Checked/Unchecked) to use when ?
Servlet:
1. What is the difference between response.sendRedirect() and request.forward() ?
How do threads work? What is synchronized? If there are two synchronized methods in a class can they be simultaneously executed by two threads. You will be surprised to hear many people answer yes. Then all thread related question, e.g. deadlock, starvation etc.
One thing many Java programmers don't know is that Strings are immutable, so use StringBuilder or StringBuffer!
String s = "";
for(int i = 0; i < 100; i++) {
s += "Strings " + "are " + "immutable, " + " so use StringBuilder/StringBuffer to reduce memory footprint";
}
This question already has answers here:
What are the effects of exceptions on performance in Java?
(18 answers)
Closed 9 years ago.
Do you know how expensive exception throwing and handling in java is?
We had several discussions about the real cost of exceptions in our team. Some avoid them as often as possible, some say the loss of performance by using exceptions is overrated.
Today I found the following piece of code in our software:
private void doSomething()
{
try
{
doSomethingElse();
}
catch(DidNotWorkException e)
{
log("A Message");
}
goOn();
}
private void doSomethingElse()
{
if(isSoAndSo())
{
throw new DidNotWorkException();
}
goOnAgain();
}
How is the performance of this compared to
private void doSomething()
{
doSomethingElse();
goOn();
}
private void doSomethingElse()
{
if(isSoAndSo())
{
log("A Message");
return;
}
goOnAgain();
}
I don't want to discuss code aesthetic or anything, it's just about runtime behaviour!
Do you have real experiences/measurements?
Exceptions are not free... so they are expensive :-)
The book Effective Java covers this in good detail.
Item 39 Use exceptions only for exceptional conditions.
Item 40 Use exceptions for recoverable conditions
The author found that exceptions resulted in the code tunning 70 times slower for his test case on his machine with his particular VM and OS combo.
The slowest part of throwing an exception is filling in the stack trace.
If you pre-create your exception and re-use it, the JIT may optimize it down to "a machine level goto."
All that having been said, unless the code from your question is in a really tight loop, the difference will be negligible.
The slow part about exceptions is building the stack trace (in the constructor of java.lang.Throwable), which depends on stack depth. Throwing in itself is not slow.
Use exceptions to signal failures. The performance impact then is negligible and the stack trace helps to pin-point the failure's cause.
If you need exceptions for control flow (not recommended), and profiling shows that exceptions are the bottleneck, then create an Exception subclass that overrides fillInStackTrace() with an empty implementation. Alternatively (or additionally) instantiate only one exception, store it in a field and always throw the same instance.
The following demonstrates exceptions without stack traces by adding one simple method to the micro benchmark (albeit flawed) in the accepted answer:
public class DidNotWorkException extends Exception {
public Throwable fillInStackTrace() {
return this;
}
}
Running it using the JVM in -server mode (version 1.6.0_24 on Windows 7) results in:
Exception:99ms
Boolean:12ms
Exception:92ms
Boolean:11ms
The difference is small enough to be ignorable in practice.
I haven't bothered to read up on Exceptions but doing a very quick test with some modified code of yours I come to the conclusion that the Exception circumstance quite a lot slower than the boolean case.
I got the following results:
Exception:20891ms
Boolean:62ms
From this code:
public class Test {
public static void main(String args[]) {
Test t = new Test();
t.testException();
t.testBoolean();
}
public void testException() {
long start = System.currentTimeMillis();
for(long i = 0; i <= 10000000L; ++i)
doSomethingException();
System.out.println("Exception:" + (System.currentTimeMillis()-start) + "ms");
}
public void testBoolean() {
long start = System.currentTimeMillis();
for(long i = 0; i <= 10000000L; ++i)
doSomething();
System.out.println("Boolean:" + (System.currentTimeMillis()-start) + "ms");
}
private void doSomethingException() {
try {
doSomethingElseException();
} catch(DidNotWorkException e) {
//Msg
}
}
private void doSomethingElseException() throws DidNotWorkException {
if(!isSoAndSo()) {
throw new DidNotWorkException();
}
}
private void doSomething() {
if(!doSomethingElse())
;//Msg
}
private boolean doSomethingElse() {
if(!isSoAndSo())
return false;
return true;
}
private boolean isSoAndSo() { return false; }
public class DidNotWorkException extends Exception {}
}
I foolishly didn't read my code well enough and previously had a bug in it (how embarassing), if someone could triple check this code I'd very much appriciate it, just in case I'm going senile.
My specification is:
Compiled and run on 1.5.0_16
Sun JVM
WinXP SP3
Intel Centrino Duo T7200 (2.00Ghz, 977Mhz)
2.00 GB Ram
In my opinion you should notice that the non-exception methods don't give the log error in doSomethingElse but instead return a boolean so that the calling code can deal with a failure. If there are multiple areas in which this can fail then logging an error inside or throwing an Exception might be needed.
This is inherently JVM specific, so you should not blindly trust whatever advice is given, but actually measure in your situation. It shouldn't be hard to create a "throw a million Exceptions and print out the difference of System.currentTimeMillis" to get a rough idea.
For the code snippet you list, I would personally require the original author to thoroughly document why he used exception throwing here as it is not the "path of least surprises" which is crucial to maintaining it later.
(Whenever you do something in a convoluted way you cause unneccesary work to be done by the reader in order to understand why you did it like that instead of just the usual way - that work must be justified in my opinion by the author carefully explaining why it was done like that as there MUST be a reason).
Exceptions are a very, very useful tool, but should only be used when necessary :)
I have no real measurements, but throwing an exception is more expensive.
Ok, this is a link regarding the .NET framework, but I think the same applies to Java as well:
exceptions & performance
That said, you should not hesitate to use them when appropriate. That is : do not use them for flow-control, but use them when something exceptional happend; something that you didn't expect to happen.
I think if we stick to using exceptions where they are needed (exceptional conditions), the benefits far outweigh any performance penalty you might be paying. I say might since the cost is really a function of the frequency with which exceptions are thrown in the running application.
In the example you give, it looks like the failure is not unexpected or catastrophic, so the method should really be returning a bool to signal its success status rather than using exceptions, thus making them part of regular control flow.
In the few performace improvement works that I have been involved in, cost of exceptions has been fairly low. You would be spending far more time time in improving the complexity of common, hightly repeating operations.
Thank you for all the responses.
I finally followed Thorbjørn's suggestion and wrote a little test programm, measuring the performance myself. The result is: No difference between the two variants (in matters of performance).
Even though I didn't ask about code aesthetics or something, i.e. what the intention of exceptions was etc. most of you addressed also that topic. But in reality things are not always that clear... In the case under consideration the code was born a long time ago when the situation in which the exception is thrown seemed to be an exceptional one. Today the library is used differently, behaviour and usage of the different applications changed, test coverage is not very well, but the code still does it's job, just a little bit too slow (That's why I asked for performance!!). In that situation, I think, there should be a good reason for changing from A to B, which, in my opinion, can't be "That's not what exceptions were made for!".
It turned out that the logging ("A message") is (compared to everything else happening) very expensive, so I think, I'll get rid of this.
EDIT:
The test code is exactly like the one in the original post, called by a method testPerfomance() in a loop which is surrounded by System.currentTimeMillis()-calls to get the execution time...but:
I reviewed the test code now, turned of everything else (the log statement) and looping a 100 times more, than before and it turns out that you save 4.7 sec for a million calls when using B instead of A from the original post. As Ron said fillStackTrace is the most expensive part (+1 for that) and you can save nearly the same (4.5 sec) if you overwrite it (in the case you don't need it, like me). All in all it's still a nearly-zero-difference in my case, since the code is called 1000 times an hour and the measurements show I can save 4.5 millis in that time...
So, my 1st answer part above was a little misleading, but what I said about balancing the cost-benefit of a refactoring remains true.
I think you're asking this from slightly the wrong angle. Exceptions are designed to be used to signal exceptional cases, and as a program flow mechanism for those cases. So the question you should be asking is, does the "logic" of the code call for exceptions.
Exceptions are generally designed to perform well enough in the use for which they are intended. If they're used in such a way that they're a bottleneck, then above all, that's probably an indication that they're just being used for "the wrong thing" full stop-- i.e. what you have underlyingly is a program design problem rather than a performance problem.
Conversely, if the exception appears to be being "used for the right thing", then that probably means it'll also perform OK.
Let's say exception won't occur when trying to execute statements 1 and 2. Are there ANY performance hits between those two sample-codes?
If no, what if the DoSomething() method has to do a huuuge amount of work (loads of calls to other methods, etc.)?
1:
try
{
DoSomething();
}
catch (...)
{
...
}
2:
DoSomething();