How to compare two enums? - java

I have two enums:
public enum UserType {
USER,
EMPLOYER
}
public enum UserDetails {
USER,
EMPLOYER
}
I try to compare this by this:
if(UserType.USER.equals(UserDetails.USER)){
return true;
}
but i can't because, my equals() throw me this:
equals() between objects of inconvertible types 'UserType' and 'UserDetails'
so, how can I compare two values from two diffrent enums?

Different types
The enum in Java is a class, albeit a slightly special kind of class. A class defines a type.
Unless related by inheritance or by interface, different types cannot be compared for equality. A String cannot be equal to a LocalDate which cannot be equal to a DataSource.
Likewise, an object of enum UserType cannot be equal to an object of enum UserDetails. Apples to oranges, not equal by definition. So, your Question is senseless, technically.
The fact that some enum classes happen to share names on some of their constants has no meaning, it is just coincidence that your two enums share the name USER or EMPLOYER. The enum Month bundled with Java defines a constant named APRIL. I might define another enum with an object also named APRIL. But that does not make them equal.
Asking this question suggests that you have a problem with your design. Perhaps you should post another Question on that design issue if it has but already been addressed on Stack Overflow. As commented by Kayaman, your Question seems like an XY Problem.
The other Answers suggesting you:
Compare the strings of the names of the enum constants.
Compare the ordinal position of the constants within the enum definition.
…are misguided. Those approaches violate the purpose of enums in Java, which is to provide a type-safe identity of certain values known at compile-time.
If you are comparing the names of the constants, then you might as well be using mere String objects rather than enums.
If you are comparing ordinal numbers, then you might as well be using mere integer numbers rather than enums.
Both cases are fragile, resulting in runtime failures if you make a change to one enum without matching the other. And in both cases you have lost the usefulness of the enum, transmogrifying the enum into a confusing level of indirection for a string or int.

Try to compare their names
if(UserType.USER.name().equals(UserDetails.USER.name())){
return true;
}
Reading other answers i've decided to give more extended answer. I have to agree thats such solution is not good enough, cause it's not about enums - it's about string comparing. Enums may be changed and everythig will not work properly. Ok.
I think that there could be better solutions - of course:
Use only one type of enum - it's perfect i think(but author has different enums)
Compare names of enums - well it's working but realy not "clever" use of enum
Make some mapping - why not - but its hard linking of two different enums and it is not good enough
enum UserType {
USER,
EMPLOYER;
public boolean isLike(UserDetails details) {
switch (this) {
case USER:
return details == UserDetails.USER;
case EMPLOYER:
return details == UserDetails.EMPLOYER;
}
return false;
}
}
enum UserDetails {
USER,
EMPLOYER;
}
if(UserType.USER.isLike(UserDetails.USER)){
// do something
}
So we see that's there is no better decision than rewrite the code and make only one enum. But everything depends on the issue:
We don't know why there are two enums - perhaps author supporting legacy code
We don't know why author has to compare these different enums
Does proposed decision solve this concrete problem - yes. Is it good - no

Related

When to use Enum class in java?

It may be very obvious questions, but is it good to use Enum class if you know that the list of values will keep increasing?
Let's say you define an Event Enum first it contains only [Poo, Too] then as we know we always have some new requirement it becomes [Poo, Too, App, Laa] and that keep changing again and again,
So what is the best approach in this case?
tl;dr
If the entire set of possible values is known at compile-time, use enum.
If values can be added or dropped while your system is in use (at runtime), then you cannot use an enum. Use a Set, List, or Map instead.
Known at compile-time
An enum is appropriate when the domain (set of all possible values) is known at compile-time.
If this year your company is offering two products ( Poo & Too ), then make an enum for those two elements.
public enum Product { POO , TOO }
Next year, your company decides to grow their product offerings by adding App & Laa. As part of a planned deployment, add two more objects to your enum.
public enum Product { POO , TOO , APP , LAA }
By the way, notice the naming conventions. The enum has a regular class name (initial cap). The objects being automatically instantiated are constants, and so are named in all-uppercase.
Also, be aware that the enum facility in Java is quite flexible and powerful, much more so than the usual naming-a-number enum scheme seen in most languages. You can have member variables and methods and constructors on a Java enum. For example, you can add a getDisplayName method to provide text more appropriate to a user-interface than the all-caps object name, as seen in DayOfWeek::getDisplayName. You can add quite a bit of functionality, such as ChronoUnit.between.
What you cannot do at runtime with an enum in Java is add or remove objects. Thus the requirement that you know your domain at compile-time. However, when working with a group of enum objects, you can use the highly-optimized EnumSet and EnumMap classes.
Known at runtime
If you cannot determine the domain at compile-time, if users can add or remove elements at runtime, then use a collection such as a List, Set, or Map rather than an enum.
Singleton
Though not originally intended as a purpose of Enum in Java, an enum happens to be the safest (and simplest) way to implement the Singleton design pattern.
This approach to a singleton is explained in the famous book Effective Java by Dr. Joshua Bloch, et al. Using an enum solves multiple obscure technical problems with other approaches to a singleton.
Your question is pretty generic and I'm pretty sure there is no single right answer. But judging based on spring* tags, I suppose you might be asking about enums in DTOs that being sent over your system in serialized form. If that's the case, I would recommend to choose String in DTO, while inside single app it's ok to use enum. Then you would just care about deserialization/conversion in a factory manner, having ability to handle unknown/missing constant gracefully by logging/providing fallback or meaningful error.
It depends on a case-by-case situation and your question doesn't have much context. However, I do recommend using ENUMs for many cases, including if you expect the list of ENUMs to increase.
Some reasons to use them are:
It creates a definite guide of ENUM elements that can be used throughout your code. It eliminates uncertainty over what something is named or what it is. For example ENUM that contains list of animals, or enum of "something".
Its easy to refactor later if you need to change anything.
I'm sure there are many more reasons, I find it like a table of contents sometimes. For many cases, you can completely avoid it and be fine but I think its better to use it in general if you're on the fence.

enums to do the computation

Can we pass objects to enum abstract methods and do a computation in enums? Here is a scenario, I have four constants and each one have their own value assigned to it. Based on the constants I will do the computation in my method.. Instead I would like to do the computation in enum and would like to get the response. To do the computation in enum I have to pass two/three reference objects to the enum methods...
ex: Consider school as enum, constants are TEACHER(LOWLEVELACCESS), STUDENT(NOACCESS), OFFICEADMIN(OFFICEACCESS).
In enum, I have abstract method process which is receiving USER POJO , strings as arguments and update some fields in the object and return the same USER POJO (with updated) to the caller. By this I can sync up the constants and their logic in enum itself.
So my question,
Is it alright to have this implementation in enum? (I have seen most of the examples treat enums to store constant values not using them for any computation)
This computation can be done by using methods in classes, what is the benefit if I do the computation in enum methods?
Is it possible to create getter/setter method in enum?
Thanks In Advance!!
IMHO:
Is it alright to have this implementation in enum?
Yes - I do it all the time.
enum Ops implements Op {
Nop{
#Override
public int filter(int old, int now) {
// Unchanged.
return now;
}
},
Diff{
#Override
public int filter(int old, int now) {
return a(now)
| (Colour.MidGrey + (r(now) - r(old))) << 16
| (Colour.MidGrey + (g(now) - g(old))) << 8
| (Colour.MidGrey + (b(now) - b(old)));
}
};
}
This computation can be done by using methods in classes, what is the benefit if I do the computation in enum methods?
The code for the functionality is in one place. This is always a good thing.
Is it possible to create getter/setter method in enum?
Yes - but don't. Remember that there is one instance of each enum for the lifetime of your code. Adding/removing functionality on a global object is very likely to hurt you later.
Is it alright to have this implementation in enum?
It is a design choice.
Enum brings some advdantanges to provide service operations.
Enum values are singletons out of the box, these are self explanatory, there are memory efficient, etc... but have also some limitations, you cannot directly derive from an enum, so you should introduce an interface behind the enum if you want to be able to test your code and avoid coupling the client classes that do the computation with the enum ... if later you change your mind about the enum usage.
This computation can be done by using methods in classes, what is the
benefit if I do the computation in enum methods?
You reason in terms of objects. You don't need to create a service and indirection in the code since the enum that is a domain object does the computation.
The enum values and the processings associated make part of the same concern. So, gathering them is not necessary a bad smell.
Nevertheless, be aware if you start to write a lot of processing that do very different things in the enum methods, you should probably get them out the enum.
This is a bad smell as the enum should not become a god object.
Is it possible to create getter/setter method in enum?
Providing data, yes but setting data of the enum : no, you must not.
Otherwise you build a stateful service and you risk to finish with synchronization concerns.
Enums are defined to be final. Computations are allowed as far as the result is equal for the same input.
You also can modify the input instance, but you should not define any setter in your enum due the enum is not immutable in that case.
See also Example 8.9.2-4 here

What is the difference between Enum and Constant Java class? [duplicate]

This question already has answers here:
What's the advantage of a Java enum versus a class with public static final fields?
(18 answers)
Closed 8 years ago.
I am getting confused regarding Enum.
Where and how to use Enum?
If I will use Enum instead of constant then what could be the benefit?
Could someone please explain to me?
The primary advantage is type safety. With a set of constants, any value of the same intrinsic type could be used, introducing errors. With an enum only the applicable values can be used.
An Enum class is used to specify a range of constants that will be frequently used within an application.
From http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html:
You should use enum types any time you need to represent a fixed set of constants.
Common examples include compass directions (values of NORTH, SOUTH, EAST, and WEST) and the days of the week.
A constant class (assuming this is what you are talking about), is really specified for one solid object that you wouldn't change. Technically, an Enum class is a constant class with more definitions, but an advantage to an Enum class is some pre-defined functions that you would have to define in your own constant class. However, you should also note that this may be overkill for small, singleton examples.
Additionally, Enum classes are type-safe, whereas static fields aren't. Compile time error checking is now possible, versus the run-time potential errors that will occur with a constant class. This furthermore improves readability, because instead of having errors where an index of a list of constants is unavailable. This is all well explained in this post, by the current best answer.
As of Java 8.0 the keyword "constant" does not exist.
If you mean "const":
This keyword is in the known keywords in Java (from the beginning until today - 8.0),
but it has no use and any compiler shouldn't compile if it find's this keyword.
Enumerations:
Use them when you have specific logical values and don't want to handle them in String,
like:
public enum AcceptableColours {
BLACK,
WHITE,
GREY
}
It's much safer during development time to match enum values
AcceptableColours currentColour = object.getColour;
if (currentColour == acceptableColours.BLACK) {
// do something
} else if (currentColour == acceptableColours.WHITE) {
// do something different
}
than to match string values
AcceptableColours currentColor = object.getColour;
if (currentColor.equals("black")) {
// do something
} else if (currentColor.equals("white")) {
// do something different
}
... imagine huge applications with much more variations on enum values (like banking software, insurance software, ...), where it's much easier to misspell some string values,
and voilà, happy debugging...

Should I be concerned about this compareTo/equals/hashCode implementation?

I'm in the middle of QA'ing a bunch of code and have found several instances where the developer has a DTO which implements Comparable. This DTO has 7 or 8 fields in it. The compareTo method has been implemented on just one field:
private DateMidnight field1; //from Joda date/time library
public int compareTo(SomeObject o) {
if (o == null) {
return -1;
}
return field1.compareTo(o.getField1());
}
Similarly the equals method is overridden and basically boils down to:
return field1.equals(o.getField1());
and finally the hashcode method implementation is:
return field1.hashCode;
field1 should never be null and will be unique across these objects (i.e. we shouldn't get two objects with the same field1).
So, the implementations are consistent which is good, but should I be concerned that only one field is used? Is this unusual? Is it likely to cause problems or confuse other developers? I'm thinking of the scenario where a list of these objects are passed around and another developer uses a Map or Set of somesort and gets unusual behaviour from these objects. Any thoughts appreciated. Thanks!
I suspect that this is a case of "first use wins" - someone needed to sort a collection of these objects or put them in a hash map, and they only cared about the date. The easiest way of implementing that was to override equals/hashCode and implement Comparable<T> in the way you've said.
For specialist sorting, a better approach would be to implement Comparator<T> in a different class... but Java doesn't have any equivalent class for equality testing, unfortunately. I consider it a major weakness in the Java collections, to be honest.
Assuming this really isn't "the one natural and obvious comparison", it certainly smells in terms of design... and should be very carefully document.
Strictly speaking, this violates the Comparable spec:
http://download.oracle.com/javase/6/docs/api/java/lang/Comparable.html
Note that null is not an instance of any class, and e.compareTo(null) should throw a NullPointerException even though e.equals(null) returns false.
Similarly, it looks like the equals method will throw NPE on equals(null) instead of returning false (unless of course you "boiled" out the null handling code).
Is it likely to cause problems or confuse other developers?
Possibly, possibly not. It really depends on how large your project is and how widespread/"reusable"/long-lived your object source code is expected to be used:
Small/short-lived/limited use == probably not a problem.
Large/long-lived/widespread use == counter-intuitive implementation may cause future problems
You shouldnt be concerned with it, if field1 is really unique. If it`s not, you may have problems. Anyway, my advise is to do some unit tests. They should show the truth.
I don't think you need to be concerned. The contract between the three methods is kept and it's consistent.
Whether it's correct from a business logic point of view is a different question.
If e.g. field1 maps to a primary key in the database it's perfectly valid. If field1 is the "firstname" of a person, I would be concerned

Java enums vs constants for Strings

I've switched from using constants for Strings to using enums. Many times I need the String representation of the enum (for logging, to pass to an API that requires a String, etc).
With String constants, you can just pass the String value, but with enums you have to call toString(). Is there a way you can "default" to the String value when supplying the enum variable?
As many posters have commented, perhaps one shouldn't be using enums if you frequently need the String representation.
You should fully adopt enum and not use the String representation in the first place. Only use the toString() to generate messages, logs, etc, but internally you'd want to work with enum. Any Map, Set, etc operations should be done on the enum type, which guarantees proper serialization, singleton pattern, and everything else that enum types are supposed to have.
In your snippet:
Object o = map.get(Options.OPTION_1);
//This won't work as intended if the Map key is a String
Compile-time error aside, you should really question whether the map key should even be of type String in the first place. The way you're using it, it looks like it should be a Map<Options, Something>.
There are a lot of good reasons to use Enum in Java. But not if you only need a String.
For example, if you are representing a specific set of entities and don't want them to be type-equivalent with other kinds of things (like Strings), then an Enum would be appropriate. Moreso if you are going to be calling functions that operate them and differentiate based on the particular instance.
On the other hand, if you are only interested in the String value of something, then there is nothing wrong with a String constant.
From what you've posted, I can't tell what the use case is. Is there some reason you need to use Enum here?

Categories