This question already has answers here:
Why Java does not allow overriding equals(Object) in an Enum?
(6 answers)
Closed 6 years ago.
I want to compare Enum's value as in example.
public enum En{
Vanila("Good"),
Marlena("Luck"),
Garnela("Good");
private String value;
private En(String s){
this.value = s;
}
}
AS Vanila and Garnela have the same value comparing them should return true. There are two ways one is == operator and second is equals() method. I tried my own logic and add this method to enum.
public boolean compareValue(En e){
return (this.value).equals(e.value);
}
and Now it's working fine.
En a = En.Vanila;
En b = En.Garnela;
En c = En.Marlena;
if(a.compareValue(b)){
System.out.println("a == b");
}
if(a.compareValue(c)){
System.out.println("a == c");
}
if(b.compareValue(c)){
System.out.println("b == c");
}
I know we can't override equals methods in enum ( Don't know why, I know that is final but not a logically reason. Can you also explain, why we can't override equals() in enum?).
Any how is there any other way to do this effectively or is it fine?
In enum each instance is meant to represent a distinguished thing. The enum value is used to describe that thing, make it human readable, etc.
Therefore there's no reason for your code to consider that Vanilla could be equal to Marlena. And it makes no sense to set the same string values for both of them.
Related
This question already has answers here:
Java Hashset.contains() produces mysterious result
(3 answers)
HashSet allows duplicates
(6 answers)
HashSet adds duplicate entries despite implementing both hashCode() and equals()
(2 answers)
Closed 3 years ago.
I was messing around trying to understand how HashSets behave and I've run into this problem that I can't get my head around. The 2nd and 3rd dog objects have the same name, and equals() and hashcode() have been overriden to make names mean equality. Despite this, the hashSet still has duplicates, and I can't figure out why.
I reread the data structures chapter of Head First Java but it still suggests that my code should work in theory.
public class DataStructsTests<E> {
HashSet<Dogs> tree = new HashSet<Dogs>();
HashSet<Dogs> treeOwner = new HashSet<Dogs>();
public static void main(String[] args) {
DataStructsTests<String> d = new DataStructsTests<String>();
d.go();
}
public void go() {
Dogs dog = new Dogs("Scout", "a");
tree.add(dog);
treeOwner.add(dog);
Dogs dog2 = new Dogs("Brodie", "b");
tree.add(dog2);
treeOwner.add(dog2);
Dogs dog3 = new Dogs("Brodie", "c");
tree.add(dog3);
treeOwner.add(dog3);
System.out.println(tree);
System.out.println(treeOwner);
System.out.println(dog2.equals(dog3));
System.out.println(dog2.hashCode() + " " + dog3.hashCode());
}
class Dogs {
private String name;
private String ownerName;
public Dogs(String n, String o) {
name = n;
ownerName = o;
}
public boolean equals(Dogs d) {
return name.equals(d.getName());
}
public int hashCode() {
return name.hashCode();
}
public String getName() {
return name;
}
public String toString() {
return name;
}
Running the program returns this:
[Brodie, Brodie, Scout]
[Brodie, Brodie, Scout]
true
1998211617 1998211617
Even though equals() returns true and the hashcodes are the same, the duplicates still remain.
Edit: Turns out the problem was that I hadn't overridden the equals() method properly as I used Dog rather than Object.
equals takes an object of type Object, which is the one being called by HashSet. You need something like:
#Override
public boolean equals(Object d) {
if (! d instanceof Dogs){
return false;
}
return name.equals(((Dogs) d).getName());
}
Here are the components of this answer:
public boolean equals(Object d) - equals, at least the version inherited from Object, is defined to take Objects, so to override it, you must also take an Object.
#Override - tells the compiler to warn you if you make a mistake like you made in your question.
d instanceof Dogs - checks if the Object fed in is even a Dogs in the first place.
((Dogs) d).getName() - The reason for the cast to Dogs is because d is now being passed in as an Object, so you won't automatically gain access to Dogs's methods unless you explicitly say that you want to view the Object as a Dogs.
And one final note: the general convention in Java is to name classes in the singular, unless there is some reason to believe that each instance will be multiple somethings. This is to avoid ambiguity. Dog d makes clear what d is; it is clearly a Dog. What, exactly, is a Dogs d? Is d many dogs, and they just don't have their own object type? It becomes a little ambiguous.
This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 7 years ago.
I have this
public void otis() {
println("What is Otis?");
String otis = readLine(">");
println("You said " + otis);
println(otis);
println(otis);
if (otis == "dog"){
println("you got it right!");
}
else {
println("try it again!");
otis();
}
}
But for some reason even when I respond "dog" it doesn't find a match. I can print the "otis" variable and it says "dog" but apparently that's not equivalent to "dog" somehow?
Can you try the code below? Java doesn't recognize strings as equivalent from two different instantiations even if their values are equivalent. This is because each string is a pointer, and their pointer values aren't equivalent. Try using the String.equal method!
otis.equals( "dog" )
Because == means "is the same exact object in memory", the constant string "dog" and the string it reads from the console are not the same object, even if they have the same contents. When doing comparisons in Java, always use .equals().
As a possible side effect of this, you have to be careful when comparing things that might be null in Java. If you try to do
String dog = null;
if(dog.equals("dog")) { do_something(); }
You'll end up with a NullPointerException. For this reason, many coders prefer to compare strings like this:
if("dog".equals(dog)) { do_something(); }
since you always know the constant string will not be null.
This question already has answers here:
Difference between Equals/equals and == operator?
(11 answers)
Closed 8 years ago.
I am studying some example code that enrol customer into a service, and the method below checks if the customer has that type of service. I assume that if we want to compare to objects, i.e. service, we need to use equals() method.
However the code below (in customer class) works perfectly fine, but it did't work after I changed == to equals.() Can someone help to explain why it behave like this? Is it because under some circumstances we need check equality using ==? Many thanks!
boolean hasService(Service sd) { //Service is a class that has int, String and ArrayList as variable
boolean hasService = false;
for (int i=0; i<.length; ++i) { //
//doesn't work if change to ((serviceAvailable[i] ).equals(pd)), why?
if (serviceAvailable[i]==sd) //serviceAvailable is an Array stores different services
hasService = true;
}
return hasService;
}
The class Service is as below:
class Serivce {
private String name;
private int price;
private ArrayList <Customers> customersErolled;
//geters and setters methods
boolean equals (Serive a){
if (this.paperName.equals(a.paperName)&&a.semester==this.semester&& a.year==this.year&&a.studentsEnrolled.equals(this.studentsEnrolled) ){
return true;
}else{
return false;
}
The equality operator == will compare the object references, while equals will depend on the implementation of equals on the object that you are comparing. By default this will compare the hash of the object (which is unique for each object in the jvm that your code runs in at that moment).
For a propper equals you need to override the equals method in Service and compare the instance variables there one by one (or whathever kind of equality you want / need).
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Integer wrapper class and == operator - where is behavior specified?
I known Java integer use cache in -127~128.
If
Integer i = 1;
Integer j = 1;
Integer m = 128;
Integer n = 128;
i == j // true
m == n // false
But I met a strange phenomenon.First,look at following snippet.
List<CustomerNotice> customerNotice = findByExample(example); // use Hibernate findByExample method
for(CustomerNotice n : customerNotice){
if(n.getConfirmStatus() == NoticeConfirmStatus.UNCONFIRMED.getValue()){
// do sth
}
}
public enum NoticeConfirmStatus{
UNCONFIRMED(1), //
CONFIRMED(2), //
FAILED_TO_CONFIRM(3); //
private final Integer value;
private NoticeConfirmStatus(Integer value) {
this.value = value;
}
public Integer getValue() {
return this.value;
}
}
public class CustomerNotice {
#Column(name = "CONFIRM_STATUS")
private Integer confirmStatus;
public Integer getConfirmStatus() {
return this.confirmStatus;
}
public void setConfirmStatus(Integer confirmStatus) {
this.confirmStatus = confirmStatus;
}
}
Although the if expression is not recommended, I think it will be return true,because n.getConfirmStatus()==1, but the result is false.I'm very confusing.
In addition, theList<CustomerNotice> customerNotice acquired by Hibernate findByExample method. Is there some Autoboxing or new operation when retrieve the resultset?
Thank you.
SHORT: (answers question)
If you want to compare Integers as the objects, you should use .equals:
i.equals(j);
m.equals(n);
With this, they should both return true. But if you really want to use ==, you need to get the primitive int value:
i.intValue() == j.intValue();
m.intValue() == j.intValue();
LONG: (explains answer)
The basis of this is that Objects are always stored separately in memory (except for some special cases like m=n), and to be compared properly, they need to be broken down into primitive types that can be compared successfully using ==.
Every Object has a .equals() method, which is inherited from Object as its superclass. However, it must be overridden to do a proper comparison. Integer overrides this method to compare to Integer objects successfully, while using == checks to see if both objects point to the same space in memory, and because two instances of an Object cannot point to the same space in memory, this will always return false.
However, as your code points out, there are some special cases that work, like these:
Your code uses a Integer i = 1, which is considered a "standard instance" and is able to be compared using ==.
If you set one Object equal to another using =, Java tells both objects to point to the same location in memory, which means that == will return true.
There are many others, but those are the two that come to mind and seem relevant.
You'll drive yourself crazy and waste a lot of time trying to figure out specific cases where this works or does not work. It depends on the implementation of code which isn't always visible to you.
The bottom line: never, ever, use == to compare Integer instances, period. As you have seen, it works sometimes, under some circumstances, and fails miserably the rest of the time. If you have a method that returns an Integer, then assign the value to an int, and then you can use == to compare that int to another int.
This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
Java String.equals versus ==
whats the difference between ".equals and =="
public String getName() {
return new String("foobar");
}
if(getName() != "foobar2") {
//Never gets executed, it should, wtf!.
}
if(!getName().equals("foobar2")) {
//This works how it should.
}
So yeah my question is simple.. why doesn't != behave the same as !equals() aka (not Equals).
I don't see any logicial reason why one should fail, both are the same exact code in my mind, WTH.
Looking at java operators
http://download.oracle.com/javase/tutorial/java/nutsandbolts/operators.html
You can clearly see
equality == !=
are the equality operators, sure I usually use != only on numbers.. but my mind started wandering and why doesn't it work for String?
EDIT:
Here's something that looks more like the actual issue..
for (ClassGen cg : client.getClasses().values()) {
final ConstantPoolGen cp = cg.getConstantPool();
if(cp.lookupInteger(0x11223344) != -1) {
for (Method m : cg.getMethods()) {
System.out.println("lots of class spam");
if(m.getName() != "<init>") continue;
System.out.println("NEVER GETS HERE, 100% SURE IT HAS CONSTRUCTOR LOL");
}
}
}
Using != means that you check for the instance reference in the memory, and the same instance will give you true on that comparison.
When you do a new String("foobar"), a new "foobar" is created in the memory, and the comparison using == returns false.
Calling a intern() on that new string may change this behavior, since the String will now be grabbed or added to the String pool.
In any case, it's safer to use the 'equals()'.
public static void main(String[] args) throws Exception {
if (getName() != "foobar2") {
System.out.println("1");
}
if (!getName().equals("foobar2")) {
System.out.println("2");
}
}
public static String getName() {
return new String("foobar");
}
For me this outputs:
1
2
But those two checks are not equivalent. The first check is checking whether the object returned by getName() is the same object that was created for the string literal "foobar2", which it's not. The second check is probably the one you want, and it checks that the VALUE of the String object returned by the getName() method is equal to the VALUE of the String object created for your "foobar2" string literal.
So both checks will return true, the first one because they aren't the same object and the second one because the values aren't the same.
A string is an Object, not a primitive.
== and != compare two primitives to each other.
To compare strings you need to loop trough each character and compare them in order which is what .equals() does.
If you do any OOP in Java you need to override equals when you want to do equality checks on the Objects, and implement Comparable and .compare() if you want to be able to do things like sort them.
Here is a quick example of equals:
public class Person {
public name;
public Person(String name) {
this.name = name;
}
public boolean equals(Object o){
if(o instanceof Person)
if(this.name.equals(o.name))
return true;
return false;
}
}
Now a Person can be compared to another Person like:
person1.equals(person2)
Which will only return true if both people have the same name. You can define what makes two objects equal however you want, but objects are only == if they are really just two pointers to the same object in memory.
Operators only apply to primitives, not Objects, so a String comparison must be done equals, as that operates at the Object level.
--EDIT--
My comment was meant more along the lines of "the value of an Object cannot be compared in the expected way as in other languages". Of course you can use == signs, but not for a textual comparison. This is the classic question that is asked every time someone migrates to Java from a scripting language, or another language that does support operators for text comparison on Strings.