Java enumeration as BigInteger value - java

I have Enumeration classes in my application and I am using this enumerations to compare value of BigIntegers like this:
if (user.getObjId.equals(RoleEnum.ADMIN.getValue())) {
//something happens
}
The question is, can I modify this enumeration class to use it without calling getValue() method, as shown in following code sample?
if (user.getObjId.equals(RoleEnum.ADMIN)) {
//something happens
}
Here is my Enumeration class:
public enum RoleEnum {
ADMIN(1), USER(2);
private final BigInteger value;
private RoleEnum(int value) {
this.value = BigInteger.valueOf(value);
}
public BigInteger getValue() {
return value;
}
}

the idea behind BigInteger is that you can work with numbers that are so big you can just type in a numeric way on the IDE...
you should do:
ADMIN("1"), USER("2");
private RoleEnum(String value) {
this.value = BigInteger.valueOf(value);

The answer to your question is simply 'No'.
It all depends on the equals method of the objectId. You can not override the equals method of the enum, but you could possibly override/declare the equals method on the objectId (it's hard to say from the information you provided).
The implementation of the equals method can then check for the type of the parameter to be of the enum type, and in that case, compare the values. For example:
public boolean equals(Object o){
if(o instanceof RoleEnum){
return this.value.equals(((RoleEnum)o).getValue());
}
...
}
But I assume, your objId is of type BigInteger, so you cant override the equals method. In that case, the answer is as mention above: 'No'

If something's not very neat refactor out a method so it looks neat again (especially if it happens in more than one place):
if (user.isRole(RoleEnum.ADMIN))
on User (I'm assuming the name of the type of user):
public boolean isRole(RoleEnum role) {
return getObjId.equals(role.getValue());
}
Or if it's not not possible to modify User or reference the enum from there, then maybe a static:
public final class UserHelpers {
private UserHelpers(){}
public static boolean userIsRole(User user, RoleEnum role) {
return user.getObjId.equals(role.getValue());
}
}
Usage:
if (UserHelpers.userIsRole(user, RoleEnum.ADMIN))
Or with the static imported:
if (userIsRole(user, RoleEnum.ADMIN))

Related

Convert parametized Enum to Enumerated Annotation in android

I have a question regarding to the andriod #IntDef Annotation. I know
that in its basic usage, it should replace the enum. But what if
I have a parameterized enum with multiple hardwired values for example
public enum MyEnum {
YES(true, 1),
NO(false, 0);
private boolean boolState;
private boolean intState;
MyEnum(boolean boolState, int intState) {
this.boolState = boolState;
this.intState = intState;
}
public boolean getBoolState() {
return boolState;
}
public int getIntState() {
return intState;
}
}
How would this be replaced by an Enumerated Annotation in Android?
Is it even suggestive to do something like that in this case? I searched
everywhere, but I haven't found any answer for that.
Thank you in advance!
I don't think you would be able to find anything because:
IntDef is a way of replacing an integer enum where there's a parameter
that should only accept explicit int values.
you can read more about it here. Enumerated annotations are for simple types, you could use it for strings also StringDef. Use enum when you need its features. Don't avoid it strictly. For your case I think creating class instead of enum would look like this:
public class MyEnum {
public static final MyEnum YES = new MyEnum(true, 1);
public static final MyEnum NO = new MyEnum(false, 0);
private boolean boolState;
private int intState;
MyEnum(boolean boolState, int intState) {
this.boolState = boolState;
this.intState = intState;
}
public boolean getBoolState() {
return boolState;
}
public int getIntState() {
return intState;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyEnum myEnum = (MyEnum) o;
return boolState == myEnum.boolState && intState == myEnum.intState;
}
}
and you could use constants in your code. But if using enums you will have type checking (you'll be able to accept only listed values) and method overloading (every enum constant can have its own implementation of a method). If you want to use less space and that is the only reason why you want to avoid using enum I would suggest you that it's not worth it.
I follow a rule with enums in Android development:
if it has no params, use an intdef/stringdef,
if it has params, use an enum
If there is a way around using an enum, I'll certainly consider it where it doesn't undermine the code.
A lot was made from the video Colt Mcanlis posted: https://www.youtube.com/watch?v=Hzs6OBcvNQE&feature=youtu.be
however it had some fairly shaky numbers in it as pointed out by Jake Wharton: https://plus.google.com/+JakeWharton/posts/bTtjuFia5wm
The main drawback of enums is that they use more memory than constants would, but if that enum aids in better code, I say use it rather than micro-optimise. Just don't go overboard using them and be aware of their footprint.
I'm coming late, but anyways, since intdef ins an annotation, you can create an annotation using a custom class and then use it in the same way. given the fact an annotation needs primitives, you'll have to pass an interface as the annotation class type, and use subclasses as the value array.
example:
public interface GenericContainer<T, X> {
public T getValueOne();
public X getValueTwo();
}
then an implementation for true/1
public class TrueContainer implements GenericContainer<Boolean, Integer> {
#Override
public Boolean getValueOne() {
return true;
}
#Override
public Integer getValueTwo() {
return 1;
}
}
and other for false/0
public class FalseContainer implements GenericContainer<Boolean, Integer> {
#Override
public Boolean getValueOne() {
return false;
}
#Override
public Integer getValueTwo() {
return 0;
}
}
finally, use them:
#Retention(RetentionPolicy.SOURCE)
#GenericDef({TrueContainer.class, FalseContainer.class})
public #interface genericTest{}
boolean test = isTest(new FalseContainer());

No Enum constant found for type in java

I am using enum in java, Here is the enum
public enum AbuseSectionType{
MUSIC("Music"), DANCE("Dance"), SOLO("Solo"), ACT("Act")
private String displayString;
AbuseSectionType(String displayValue) {
this.displayString = displayValue;
}
#JsonValue
public String getDisplayString() {
return displayString;
}
public void setDisplayString(String displayString) {
this.displayString = displayString;
}
}
I am trying to get value AbuseSectionType.valueOf("Music"). I am getting no enum constant and found no error. I am supposed to have value MUSIC.
The name() of an enum is the name specified when declaring it, MUSIC in your case.
If we read the javadoc for valueOf():
Returns the enum constant of the specified enum type with the
specified name.
valueOf() is using the name() of the enum. But what you want to achieve is different, so you cannot use this method. What you can do instead is to make your own method that finds the value from your own field (displayString).
Here's an example:
public static AbuseSectionType fromDisplayString(String displayString)
{
for(AbuseSectionType type : AbuseSectionType.values())
if(type.getDisplayString().equals(displayString)
return type;
return null; //not found
}
The default valuOf() method will only retrieve the respective enmum if the exact spelling of the enum-definition is used. In your case you have defined the enum MUSIC so in order to get that one you have to do it like this: AbuseSectionType.valueOf("MUSIC");
In order to achieve what you seem to want you have to implement a method in the enum class by yourself. For your example you could do somthing like this:
public AbuseSectionType resolve(String name) {
for(AbuseSectionType current : AbuseSectionType.values()) {
if(current.displayString.equals(name)) {
return current;
}
}
return null;
}
use AbuseSectionType.valueOf("MUSIC") pass the name of enum. See java docs regarding use of valueOf

How can I use a third party Class Object as Hashmap Key?

OK I understand the working of equals and hashcode and How they are used in hashmap.
But This question crossed my mind What if I am having a third party object which does'nt have overridden hashcode and equals and I am not even allowed to modify it.
Consider following Class:
//Unmodifiable class
public final class WannaBeKey{
private String id;
private String keyName;
//Can be many more fields
public String getId()
{
return id;
}
public String getKeyName()
{
return id;
}
//no hashcode or equals :(
}
Now I want to make this class as my Hashmap key obviously it won't work without equals and hashcode. I want to know is there any way to handle such cases? I am unable to think of any or I am way over my head..
Thanks.
I've encountered this previously, and worked around it by creating a wrapper for the WannaBeKey as such:
public class WannaBeKeyWrapper {
private final WannaBeKey key;
public WannaBeKeyWrapper(WannaBeKey key) {
this.key = key;
}
public boolean equals(Object obj) {
// Insert equality based on WannaBeKey
}
public int hashCode() {
// Insert custom hashcode in accordance with http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode()
}
}
Obviously this changes your Set from Set<WannaBeKey> to Set<WannaBeKeyWrapper>, but you should be able to account for that.
You can create a wrapper for that object which will have the overridden methods. Then you can use the wrapper class as the key of your hash map.
You can wrap the actual object in another instance with the required semantics:
class KeyWrapper {
WannaBeKey key; // constructor omitted
#Override
public int hashCode() {
return key.getId().hashCode();
}
#Override
public boolean equals(Object o) {
// equals method implementation
}
}
Alternatively, you could simply extend the class (if the class was not final as you stated in your edit).
This question has already been answered thoroughly but I thought it was worth mentioning that the solutions above are part of a specific design pattern known as a Decorator.
The Adapter or Wrapper pattern uses essentially the same solution but is meant more for transforming code to a different interface whereas Decorator is used for extension.

Java return correct type of enum

If I have the following
public enum MY_ENUM_THING
{
NAME("JOE"),
SOMETHING,
ISWORKING(true);
private String parameter;
private boolean truth;
MY_ENUM_THING()
{
}
MY_ENUM_THING(String parameter)
{
this.parameter = parameter;
}
MY_ENUM_THING(boolean truth)
{
this.truth = truth
}
public ?? getEnumValue()
{
// this method (return) is what would be jamming me up
}
}
How do I get my return to return whatever the type of the enum is?
Example and desired results
System.out.print(MY_ENUM_THING.NAME.getEnumValue());
//JOE
System.out.print(MY_ENUM_THING.SOMETHING.getEnumValue());
//SOMETHING <-- just return SOMETHING.name()
System.out.print(MY_ENUM_THING.ISWORKING.getEnumValue());
//true
Find a better design. Java does not work well like this. The only common class to all return types is Object (boolean -> Boolean). Do you want to check the class of the return type every time you call this method before you cast it to the appropriate type.
Your design is also bad as enums are meant to represent a finite set of values each with the same type and properties. You are creating three totally different objects that represent three different things.
You need to look at your use case and come up with a better design. You could even post a separate question asking for advice.
You can't write such a method, it has different return types for each case! (unless you returned Object, but that would be messy.) As a matter of fact, I smell a design problem - every enumeration value should have values for each of its attributes, it's problematic to have values for some attributes and not for others.
This should do the trick:
public String getEnumValue()
{
if(parameter != null){
return parameter;
}
if(truth != null){
return Boolean.toString(truth);
}
return name();
}
You should also change your boolean to a capital-B 'Boolean'
But, as others are saying, this may be questionable design.
To answer the real question "how do I return the type that matches the given varible?" You don't. You can, however, make the return value an Object if you want to preserve the actual return type of the value:
public Object getEnumValue()
{
if(parameter != null){
return parameter;
}
if(truth != null){
return truth;
}
return this;
}
What exactly is wrong with classes and interfaces?
interface Thing<E> {
E getValue();
}
class Name implements Thing<String>{
private String parameter;
Name(String p){parameter = p;}
String getValue(){return parameter;}
}
class Something implements Thing<Void>{
Void getValue(){return null;}
}
class IsWorking implements Thing<Boolean>{
private boolean truth;
IsWorking(boolean t){truth = t;}
Boolean getValue(){return truth;}
}

Mutable boolean field in Java

I need a mutable boolean field in Java (I will return this field via get* method later and it should be possible to modify this field).
Boolean doesn't work because there are no set* methods in the Boolean class (I would say that Boolean is immutable, you can only change the reference, but you can't change the object itself).
I guess I can use Boolean array of size 1. But probably there are more elegant solutions?
Why doesn't Java have such a simple thing?
Immutable classes are easier to work with. They'll never change and there will be no problems with concurrent code. (Basically, there are fewer possibilities to break them.)
If you would like to return a reference to your Boolean value, you can use java.util.concurrent.atomic.AtomicBoolean if you're working with multiple threads or plain old org.apache.commons.lang.mutable.MutableBoolean.
Maybe write yourself a wrapper class
class BooleanHolder {
public boolean value;
}
Or make a generic holder class (which means you will have to use class Boolean instead of primitive boolean):
class Holder<T> {
public T value;
}
You then return the wrapper class instead of the value itself, which allows the value inside the wrapper to be modified.
If you are using Java 5 or higher then use AtomicBoolean
You can use a boolean array
final boolean[] values = { false };
values[0] = true;
What about just using the boolean primitive?
private boolean value;
public void setValue(boolean value) {
this.value = value;
}
public boolean getValue() {
return value;
}
Why not use the boolean primitive ?
e.g.
private boolean myFlag = false;
public void setMyFlag(boolean flag) {
myFlag = flag;
}
Note your getter method can return a Boolean if required, due to the magic of autoboxing. This allows easy interchangeability between using primitives and their object equivalents (e.g. boolean vs. Boolean, or int vs. Integer).
So to address your edited responses re. the methods you have available,
public Object getAttribute(String attributeName)
can be implemented by returning an autoboxed boolean,.
The answer I liked most was from Adam to write your own wrapper class... OK
/* Boolean to be passed as reference parameter */
public class Bool {
private boolean value;
public Bool() {
this.value = false;
}
public boolean is() {
return this.value;
}
public void setTrue() {
this.value = true;
}
public void setFalse() {
this.value = false;
}
}
If you are using Android, you can use the android.util.Mutable* objects which wrap various primitive values. For example, quoting from the SDK source:
public final class MutableBoolean {
public boolean value;
public MutableBoolean(boolean value) {
this.value = value;
}
}
Are you really saying that you want callers to be able to modify the object's boolean value by manipulating what gets returned? So that the object and caller would share a reference to it?
Just so I understand, given:
class OddClass {
private Boolean strangeFlag;
public Object getAttrbiute(String attributeName) {
if (attributeName.equals("strangeflag")) return (Object)strangeFlag;
...
}
}
And then caller does:
Boolean manipulableFlag = (Boolean) myOddClass.getAttrbiute ("strangeflag");
And then later, if caller changes the value of manipulableFlag, you want that change to happen in the OddClass instance, just as though caller had instead used a setAttrbiute method.
Is that what you're asking?
In that case, you'd need a holder class, as suggested by Adam.

Categories

Resources