Comparison Method violates its general contract. Simple comparison - java

I'm doing a card game in swing (java)
The user has to wait his turn, take a card, and press confirm. When it's not his turn, he can't take any card.
It starts this way:
this.cardTaken = false;
board.canTakeCards(!cardTaken);
Then in board class it comes the next action:
public void canTakeCards(boolean can) {
if (can) {
this.btnConfirm.setEnabled(false);
this.pnlCards.setCanTake(true);
} else {
this.btnConfirm.setEnabled(true);
this.pnlCards.setCanTake(false);
}
(the else happens when the user takes a card).
So. I got the Comparison method violates its general contract at line board.canTakeCards(!cardTaken);
That only happened one time and I "tested" my game for about 8 times. I'm really confused and afraid about this.
One of my theories is that I call this function from 2 differents parts of the code at the same execution time, and it receives a true and false at the same time. But I revised my code and i think that's imposible.
Any advice? Thanks

This message text is included in an exception thrown from Java 7 sorted collections, indicating that the object in question has an inconsistent implementation of compareTo, which basically means it is not imposing a total ordering on the objects. Prior to Java 7 this was silently ignored. Revise your Comparable classes.

Related

Empty result vs throwing exception for predictable but unpreventable failure

What is the preferred design for methods that encounter predictable but unpreventable failure? Should they return an empty result or throw an exception on failure? Please explain your reasoning.
I'll give two sample methods:
A method like Arrays.binarySearch() that returns the index of a value within an array.
Tickets.buy(20, 100). A ticket bot attempts to buy at least 20 tickets using $100. The method returns the list of tickets that were bought.
For both methods, let us assume that the user has no way of predicting whether the method will succeed in finding a match.
Method 1 can fail if:
The array does not contain the desired value.
Method 2 can fail if:
There aren't enough tickets.
There are enough tickets for sale, but they cost more than $100.
Java chose to return the equivalent to an empty result for method 1, but doing the same for method 2 wouldn't allow you to differentiate between the two kinds of errors. What are the guidelines for choosing between the two possible designs?
Please note that although this question contains two concrete methods, I am looking for general design guidelines not a specific solution to the aforementioned methods.
The best approach depends on the case.
Case 1:
Since the method returns the index of the found element, I suggest returning -1 if the desired value has not been found. Stick to the well known API of almost everyone is familiar with, like for indexOf().
Case 2:
Here I would suggest using exceptions (InsufficientMoneyException, OutOfTicketsException, ...). An empty list or null is not very meaningful and the different error cases cannot be reflected with that.
This way you can properly handle the exceptions in their respective catch blocks.
In general you have to keep in mind that throwing exceptions is expensive operations, because the stack trace has to be built.
This question is rather opinion-based, just like the whole returning null/throwing an exception/returning empty object dilemma.
I personally think that returning -1 is for the first method and throwing exceptions for your second method would be better.
Following the single responsibility principle, one method should do one thing.
The goal of the first method is to search for an element, it can either find it or not find it. This is the expected behavior.
The goal of the second method is to buy a ticket. Unlike the first method, it's not checking if it can buy a ticket or not, it's doing it. The expected behavior is that the ticket is bought. If that behavior does not happen, something went wrong, thus an exception should be thrown.
I also think that #StriplingWarrior's approach might not be ideal because if you have more than just two possible cases, you can't really have Either<A, B, C, D, E, ...>.
RIP. I spent 15 minutes writing an answer and I accidentally opened the web console and deleted the body. The last saved answer was like 10 minutes before. I don't even know how you can accidentally do that. I guess F12 and DEL are kinda close
Typically you'd want to make your return type be an object that contains all the information you're likely to need to know.
In the early days of Java, it was common to return normally invalid values like -1 (in the case of Arrays.binarySearch()) or null in order to represent the absence of a value. More modern APIs tend to return an Optional<> to provide compile-time enforcement of the concept that there may not be a result (as well as differentiating between "no result" and "the result is null).
In the Tickets.buy() example, you could have an Either<String, List<Ticket>>, where the "left" value can be a reason that the purchase failed, and the "right" value can be the tickets that got purchased if it succeeded.
I ended up taking the advice found at https://stackoverflow.com/a/77361/14731
My interpretation is as follows:
From a purist perspective, if the purpose of Arrays.binarySearch() is to return the index of an element in an array, then it should throw an exception when no match is found. The fact that no result has a negative index is a convenient fact that allows us to return -1 instead. But again, in an ideal world this method should be throwing an exception. If this method was answering the question "does the array contain this element" and returning a boolean then no exception would need to be thrown.
Tickets.buy(20, 100) assumes that a match will be found in purchase the tickets. If no match is found then an exception should be thrown.

What determines the return order of Class.getMethods()?

This question is not looking for a solution to a problem but an explanation of why a problem may have arisen (or not!).
The Javadocs for Class.getMethods() say:
The elements in the array returned are not sorted and are not in any particular order.
The thing is, this: we’ve been using a neat little Java templating library called JMTE for maybe a couple of years now, with no problems. This uses JSTL-like syntax to inject model values into templates. In particular, we’ve been using something like this to render a price:
${vendor.currency.symbol} ${order.amount}
The first of these translates to the the following:
vendor.getCurrency().getSymbol()
where getCurrency() returns a java.util.Currency object. Currency has two methods for getting the currency symbol - one that takes a specific Locale and one that uses the default.
public String getSymbol()
public String getSymbol(Locale locale)
For the last 18 months or so, everything has been running fine, with currency codes/symbols appearing in emails. Then 5 days ago, we started getting a random IllegalArgumentException thrown when trying to substitute ${vendor.currency.symbol}
After a bit of debugging I found the cause, deep inside JMTE:
for (Method method : declaredMethods) {
if (Modifier.isPublic(method.getModifiers())
&& (method.getName().equals("get" + suffix) ||
method.getName().equals("is" + suffix))) {
value = method.invoke(o, (Object[]) null);
....
}
}
i.e., Whether getSymbol() or getSymbol(Locale) was called is completely at the mercy of the return order of Class.getMethods() (not in any particular order). I added a test to ensure the method has 0 parameters and my problem was solved.
Now, by a strange coincidence, someone else happened to submit an identical fix on the very same day that we first observed this behaviour.
What’s puzzling is that this code has been running for 18 months with no problems, then all of a sudden, this behaviour appears.
When I created a test case it failed roughly 50% of the time, as one would expect (there are 2 matching methods, returned in no particular order), so I'm puzzled (amazed) it worked for 18 months and 10^5 executions. (It's conceivable, but unlikely, that it has failed but succeeded on subsequent retries).
Purely out of curiosity, I’m wondering if there’s anything in the Java runtime that might cause this latent behaviour to suddenly appear. It’s even more puzzling that a fix for this behaviour should be provided by someone else on the same day for a project that is mature and stable - suggesting perhaps that the same latent behaviour suddenly realised itself elsewhere.
So, the question is: does anyone know what factors might influence the order of the methods returned by Class.getMethods()?
The relevant Java code that can be seen from getMethods() shows a lot of checking for cached data, but the final say is up to this implementation:
private native Method[] getDeclaredMethods0(boolean publicOnly);
Therefore it's VM dependent, and a very poor idea to trust the order simply because "it was the same one a lot of times".
The caching affects it certainly, since if it's fetched correctly the first time, it'll work for the subsequent times as well unless the cache is cleared (there's some soft reference business and such going on).

ActionListener acting wierd

I am having a problem with my ActionListener's not acting as (I think) they should. I have the below code:
textField.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
final String text = textField.getText();
if (text.toLowerCase().replaceAll("'", "").contains("whats new")){
textArea.setText("Oh, you know...work...college. I am a computer science major and software engineer.\nDo you program?");
if (text.toLowerCase().replaceAll("'", "").contains("yes")){
textArea.setText("Cool!");
}else{
textArea.setText(":(");
}
}
}
});
The textField is where the user types the question, and the textArea is where the program answers.
The problem is, when I type "whats new", then "yes", it gives me the default string I set for when it doesn't understand.
You're not thinking fourth-dimensionally! (kidding aside now)
You are attempting to handle the sequence of events at once in your listener but your listener will actually be called multiple times: once for an answer to the first question and a second time for a reply to your follow-up comment.
You need to make your listener handle both of these states independently. You probably need to capture the state of your last asked question in the class scope and check it in your listener to determine what question was asked so you will know how to evaluate the contents of text and give the proper reply.
You will probably not study finite automata or formal study of state machines for several more semesters, but it's a crucial step to have elementary understanding of. Without knowing the problem statement provided, I assume the assignment is trying to push you into that direction. Also, in any paradigm, though for Java we'll stick with OO, there are many ways to add some layers of beauty and fault-tolerance for a better solution, but my intent is to stick with what is simplest for you. For example, you could make a class that represents each state pending the user's response (question 1, question 2, etc.) and model the states and transitions within your application. Each state as modeled would know of the question asked, potential answers, and transitions to other states. In an OO system, each of these states would have an API and operate via some call like execute() which would evaluate the current state of the system and determine a transition. Do some more research on this on your own.
Back to your simpler example. Let's say you only have two cases, one for each question: "what's new" and "do you program". Store some representation in your class (named constants are good practice):
class Interrogator {
String q1 = "what's new";
String a1 = ...do you program?";
String q2 = "yes";
...
}
Now in your actionPerformed, test the contents of both your question-text-area against known questions and your answer area against known responses: if (a1.equals(textArea.getText() && q2.equals(text.getText())) then you know you the answer to the initial (unprompted) question is displayed and an expected response was entered. Don't forget your formatting translation (to lower case, strip quotes).
It gives you the default because the second if statement is inside the first. When the first test is true, the second test which nested inside the first test will be false casing the else clause to override your textArea with default text. You should do something like this
if (text.toLowerCase().replaceAll("'", "").contains("whats new")){
...
}
else if (text.toLowerCase().replaceAll("'", "").contains("yes")) {
...
}
else {
...
}

Is this a bug? (recursive constructors in Java)

I've been playing with recursive constructors in Java. The following class is accepted by the compiler two examples of recursive constructors in Java. It crashes with a StackOverflowError at runtime using java 1.7.0_25 and Eclipse Juno (Version: Juno Service Release 2 Build id: 20130225-0426).
class MyList<X> {
public X hd;
public MyList<X> tl;
public MyList(){
this.hd = null;
this.tl = new MyList<X>();
}
}
The error message makes sense, but I'm wondering if the compiler should catch it. A counterexample might be a list of integers with a constructor that takes an int as an argument and sets this.tl to null if the argument is less than zero. This seems reasonable to allow in the same way that recursive methods are allowed, but on the other hand I think constructors ought to terminate. Should a constructor be allowed to call itself?
So I'm asking a higher authority before submitting a Java bug report.
EDIT: I'm advocating for a simple check, like prohibiting a constructor from calling itself or whatever the Java developers did to address https://bugs.openjdk.java.net/browse/JDK-1229458. A wilder solution would be to check that the arguments to recursive constructor calls are decreasing with respect to some well-founded relation, but the point of the question is not "should Java determine whether all constructors terminate?" but rather "should Java use a stronger heuristic when compiling constructors?".
You could even have several constructors with different parameters, calling each other wiht this(...). In general, by computer science, a termination of code can not always be guaranteed. Some intelligence, like in this simple case, would be nice to have, but one may not require a compiler error. A bit like unreachable code. There is no difference between a constructor or normal method in my eyes however.
I wouldn't see any reason why a constructor should more need to terminate than any other kind of function. But, as with any other kind of function, the compiler cannot infer in the general case whether such function ever terminates (halting problem).
Now whether there's generally much need for a recursive constructor is debatable, but it certainly is not a bug, unless the Java specification would explicitly state that recursive constructor calls must result in an error.
And finally, it's important to differentiate between recursive calls to constructor(s) of the same object, which is a common pattern for instance to overcome the lack of default parameters, and calling the constructor of the same class to create another object, as done in your example.
Although this specific situation seems quite obvious, determining whether or not code terminates is an impossible question to answer.
If you try to configure compiler warnings for infinite recursion, you run into the Halting Problem:
"Given a description of an arbitrary computer program, decide whether
the program finishes running or continues to run forever."
Alan Turing proved in 1936 that a general algorithm to solve the
halting problem for all possible program-input pairs cannot exist.

When to use an exception instead of a boolean

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);
}
}

Categories

Resources