开发者

How can I print error messages from my function when the arguments are invalid?

I just started to learn Java. There is a course in MIT and there is an assignment to write a class for pay calculation. Part of the task is:

  • The base pay must not be less than the minimum wage ($8.00 an hour). If it is, print an error.
  • If the number of hours is greater than 60, print an error message.

The code I have written is as follows:

public class fooCorporation {
    private float totalPay;
    private float calc;

    public float totalPay(double basePay, int hours){

        if(hours <= 40){
            totalPay = (float) (basePay * hours);
        }
        else if(hours > 40){
            int extraHours =  hours - 40;
            float payForFortyHours = (float) (basePay * hours);
            float payForextraHours = (float) (baseP开发者_开发技巧ay * 1.5 * extraHours);

            totalPay = payForFortyHours + payForextraHours;
        }
        return totalPay;
    }

    public static void main(String[] args){
        fooCorporation foo = new fooCorporation();
        System.out.println("employee 1: " + foo.totalPay(7.50,35));
        System.out.println("employee 2: " + foo.totalPay(8.20,47));
        System.out.println("employee 3: " + foo.totalPay(10.00,73));
    }
}

The problem I am facing is how to print an error message from the function totalPay() when some conditions are not met. Can the above logic be written in a different way?


The totalPay() method looks good as written. What you could do now is add another method that handles all of the printing. Here's some code that shows the overall idea. I've left gaps in there for you to fill in.

public void printPay(int employeeNum, double basePay, int hours) {
    if (...) {
        System.out.println("error");
    }
    else if (...) {
        System.out.println("different error");
    }
    else {
        System.out.println("employee X: " + totalPay(...));
    }
}

public static void main(String[] args){
    fooCorporation foo = new fooCorporation();

    printPay(1, 7.50,  35);
    printPay(2, 8.20,  47);
    printPay(3, 10.00, 73);
}

The nice thing about using the totalPay() function you already wrote is that it organizes the code in nice, small, manageable chunks. One function does calculations and the other handles printing. Each function has its unique role.


I suppose you should handle a negative number of hours passed in; for example:

public float totalPay(double basePay, int hours) throws Exception{
{
if(hours<0)
   throw new Exception("Hours cannot be a negative number");
if(basePay<=0)
   throw new Exception("Base pay cannot be a negative number");
   ...//the rest of the implementation
}

HOWEVER, throwing Exception as above is generally bad practice.. Defining your own Exception class and throwing specifically that Exception, when necessary (for example when a standard Java Exception does not perfectly fit in the situation at hand), is a best practice because it gives more useful information as to what had gone wrong on the program and gives the developer a chance to react in an easier, cleaner and more granular way to the specific situation. For example, some Exceptions may be considered fatal while others may be catched and easy to recover from. In cases where it makes sense to define your own Exception as opposed to using one of the Java's standard library is the following:

class BadParameterException extends Exception {
   public BadParameterException(String msg){
      super(msg);
   }
}

And in your specific example you could flag your method as throws BadParameterException as so:

public float totalPay(double basePay, int hours) throws BadParameterException {
       if(hours<0)
        throw new BadParameterException ("Hours cannot be a negative number");
 ... // and so on
 }


You generally don't print things in the middle of general purpose functions since (1) it's annoying to the people using those functions; and (2) it gives no indication of a problem to the calling code.

Usually, you would either throw an exception or have some specific return code indicating an error condition.

Then the caller can decide what to print (or do otherwise if printing is not appropriate).

For example, if you can determine that the total pay should always be positive, just return -1.0 for an error condition. For example:

public class fooCorporation {
    public float totalPay (double basePay, int hours) {
        if (hours < 0) return -1.0;
        if (hours <= 40) return (float) (basePay * hours);

        int extraHours =  hours - 40;
        float payForFortyHours = (float) (basePay * hours);
        float payForextraHours = (float) (basePay * 1.5 * extraHours);

        return payForFortyHours + payForextraHours;
    }

    public static void main(String[] args){
        fooCorporation foo = new fooCorporation();
        float pay = foo.totalPay (7.50, 35);
        if (pay < 0) System.out.println ("employee 1: invalid hours");
        else         System.out.println ("employee 1: " + pay);

        pay = foo.totalPay (8.20, 47);
        if (pay < 0) System.out.println ("employee 2: invalid hours");
        else         System.out.println ("employee 2: " + pay);

        pay = foo.totalPay (10.00, -4);
        if (pay < 0) System.out.println ("employee 3: invalid hours");
        else         System.out.println ("employee 3: " + pay);
    }
}

That method of yours, by the way, gives you double time and a half (x2.5) for overtime since you're not adjusting the base hours down to 40. Make sure that's what you want rather than time and a half (x1.5).


This calls for an exception.

In the totalPay method

if (!someConditions)
    throw new IllegalArgumentException("Condition XY not met.")

In main: surround your code with a try-catch-block

try
{
    fooCorporation foo = new fooCorporation();
    System.out.println("employee 1: " + foo.totalPay(7.50,35));
    System.out.println("employee 2: " + foo.totalPay(8.20,47));
    System.out.println("employee 3: " + foo.totalPay(10.00,73));
}
catch(IllegalArgumentException ex)
{
    System.out.println(ex.getMessage());
}

Note: read the link I posted, exceptions can be a little bit confusing, but it's a very important concept in Java.

For further reading (once you now the basics) I would recommend Exception Handling Antipatterns. It covers some common mistakes regarding exceptions.


The idiomatic way to deal with this would be to test for what ever bad data you might encounter and to throw IllegalArgumentException ( with a very detailed explanation of what was illegal and why ) or one of the other built in exceptions dealing with generic problems with invalid data.

You could also create your own sub classes of RuntimeException for more specific cases. Like BasePayLessThanZeroException or HoursLessThanZeroException or HoursGreaterThan168Exception.

The most important take away is that the cause and possible remedies of the exceptions should be well stated a clear. FILE NOT FOUND without listing the location and name of the file you were looking for is terrible. Could not find ~/settings.xml is a much better exception message.


There're a few ways to go about this. The approach you take depends upon your requirements. If you merely want to print an error message, you can check your conditions and use System.out or System.err to emit your message:

if (conditionsNotMet)
  System.err.println("Error: Condition X is not met");

Take a look at the javadoc for System.out and System.err (http://download.oracle.com/javase/1,5.0/docs/api/java/lang/System.html) -- They're both output streams, corresponding to stdout and stderr. stderr is typically used for emitting error and log messages, but how each of these outputs is used is up to you, the developer.

If you wanted to abort processing, you might consider using an exception instead:

if (conditionsNotMet)
  throw new Exception("Condition X is not met");

Consider that exceptions can be a burden on developers. Checked exceptions (http://www.javapractices.com/topic/TopicAction.do?Id=129) must be declared to be thrown or caught. In this case, perhaps that's what you want.

It's bad form to throw a java.lang.Exception -- seriously consider an exception that is more suited (such as IllegalArgumentExeception, in this case) or implement your own. IllegalArgumentException is not a checked exception which might be good in your case. As I mentioned, checked exceptions must be declared as thrown or caught in a try/catch block. Seeing as IllegalArgumentException is not checked, you won't be forcing clients of your method to catch it.

Often it's still a good idea to document when a method throws an unchecked exception, though. This informs other developers using your code the common conditions under which an exception is thrown allowing them to make a decision about catching or ignoring the exception.


Edit: just saw the link going to try to read your assignemtn

 int extraHours =  hours - 40;
//insert "if(hours > 60)printf("Mistake...");
            float payForFortyHours = (float) (basePay * hours);


public float totalPay(double basePay, int hours){
//insert "(if(basePay < 8.00) printf("mistake");


It depends on where you want to print the error message. You can, of course, print from within the totalPay() method itself, but I'm guessing you're asking about changing the "signature" of totalPay() so that the code calling it knows an error occurred.

If so, you either do that by returning a special value that means an error occurred or by throwing an Exception. Either way, your calling code will have to check that a successful return occurred before it can print the result.

An example of using a special return value would be a negative number, or a special value like java.lang.Float.NaN.

An example of using an Exception would be:

try {
    System.out.println(foo.totalPay(8.20,47));
}
catch (InvalidTotalPayException e) {
    System.out.println("Exception: " + e.toString());
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜