Convert parametized Enum to Enumerated Annotation in android - java

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

Related

Can adding conditional diagnostics in Java be zero cost when they are off?

This is really a question about Java, not c++.
The idea is you'd like to be able to add in-line diagnostics that you could turn on and off by setting a flag. And you'd like the cost to be low and near or at zero when the flag is turned off.
Years ago I implemented a class I called "Debugger" in C++ that did this. The design uses enums for the flag names so you can have code that's readable and efficient and type-safe. The usage looks like this.
enum DebugBits {
testCondition1,
testCondition2,
testCondition3
nTestConditions
}`
Debugger testDebug("testDebug", nTestConditions,
"condition1",
"condition2",
"condition3");
Critical::doStuff()
{
...
if (testDebug.on(testCondition2))
doSomethingSpecial();
...
}
This was easily implemented with bits indexed with the enum values and inline methods. It works well in a large real-time system and has very near zero cost when the debugging is turned off. Its a valuable tool.
Anyway, back to the question. Today I was looking at doing the same thing in Java, for personal reasons, but given that you can't subclass enums, and yet it would be good to use them, its not so easy to keep the declaration clear and the usage in the code brief.
So here's an implementation that works, and is somewhat efficient. The questions are,
Can the implementation be more efficient?
At the same time can the usage in the code be kept clear?
I suspect there are better Java coders out there that may have better ideas about how to do this. Add a package at the top and this should compile and run. There is another class at the bottom to demonstrate the usage. Note that there's lots more that should be in this, but this is the core part the is interesting. Well... to me.
import java.util.BitSet;
import java.util.EnumSet;
import java.util.Vector;
public class Debugger {
private final EnumSet mEnumSet;
private final BitSet mBits;
private final Vector<String> mNames;
public Debugger(EnumSet es) {
mEnumSet = es;
mBits = new BitSet(es.size());
mNames = new Vector<>();
for (Object i : mEnumSet)
mNames.add(i.toString());
}
public void set(int bit) {
mBits.set(bit);
}
public void set(String bitName) {
int bit = mNames.indexOf(bitName);
if (bit >= 0)
mBits.set(bit);
}
public boolean on(int bit) {
return mBits.get(bit);
}
public boolean on(Object arg) {
if (arg.getClass() == Enum.class) {
int bit = ((Enum)arg).ordinal();
return mBits.get(bit);
}
return false;
}
public boolean on(String bitName) {
int bit = mNames.indexOf(bitName);
return bit >= 0 && mBits.get(bit);
}
}
class SampleUsage {
static class Debug extends Debugger {
enum Bits {
zero, one, two, three;
public static final EnumSet<Bits> bits = EnumSet.allOf(Bits.class);
}
public Debug() {
super(Bits.bits);
}
}
public static final Debug debug = new Debug();
public SampleUsage() {}
void doStuff() {
if (debug.on(Debug.Bits.three))
showDebugInfo();
if (debug.on("three"))
showDebugInfo();
}
private void showDebugInfo() {}
}
I think you’ve missed the point of EnumSet<>. The EnumSet<> is your type-safe set of highly efficient debug flags.
enum Debug {
FLAG0, FLAG1, FLAG2;
}
EnumSet<Debug> debug = EnumSet.noneOf(Debug.class);
debug.add(Debug.FLAG0);
if (debug.contains(Debug.FLAG0)) {
showDebugInfo0(); // Will be executed.
}
if (debug.contains(Debug.FLAG1)) {
showDebugInfo1(); // Will not be executed because FLAG1 was not added to the EnumSet.
}
There is no need to translate the enum values into ordinals, and add that ordinal to a BitSet. EnumSet<> is already implemented using something like a BitSet (except the EnumSet<> is of a fixed size, based on the number of identifiers in the Enum, so cannot be extended to an arbitrary length).
If you want to test if a flag is set by name, you can use the Enum.valueOf() to convert the name into the correct Enum, and test if the EnumSet<> contains that.
if (debug.contains(Enum.valueOf(Debug.class, "FLAG2")) {
showDebugInfo2(); // Also not executed, because FLAG2 was not added to the EnumSet.
}
Again, no need for a Vector<String> that contains all of the Enum names, which you must find the .indexOf(). The Enum comes with that method built-in. Vector<> was not an efficient choice to use anyway, since Vector<> operations are automatically synchronized, so are slightly slower than an equivalent ArrayList<>.
Note: Minor difference: .indexOf() returns -1 when not found; Enum.valueOf() will raise an IllegalArgumentException if you give it an unknown identifier name.
Assuming you want .on(), not .contains(), and you want simpler test flag by name usage in your code, we’ll need to wrap the EnumSet<> in another class. This Debug class might look like:
class Debug<T extends Enum<T>> {
private final Class<T> enum_class;
private final EnumSet<T> flags;
public Debug(Class<T> enum_class) {
this.enum_class = enum_class;
flags = EnumSet.noneOf(enum_class);
}
public void set(T flag) {
flags.add(flag);
}
public boolean on(T flag) {
returns flags.contains(flag);
}
public void set(String flag_name) {
flags.add(Enum.valueOf(enum_class, flag_name));
}
public boolean on(String flag_name) {
return flags.contains(Enum.valueOf(enum_class, flag_name));
}
}
So with minor mods to your implementation, it shows brevity and clarity and uses fewer resources. The Enum.valueOf() I missed entirely. The string conversion is a goal I did not describe, but is useful when trying to set bits through a subsystem that is unaware of the class containing the enums, but the user knows the names. I got parts of it right, but you got me out of the weeds. Thanks much.
Oh... and I changed the name.
import java.util.EnumSet;
class Diagnostic<T extends Enum<T>> {
private final Class<T> enum_class;
private final EnumSet<T> flags;
public Diagnostic(Class<T> enum_class) {
this.enum_class = enum_class;
this.flags = EnumSet.noneOf(enum_class);
}
public void set(T flag) {
flags.add(flag);
}
public boolean on(T flag) {
return flags.contains(flag);
}
public void set(String flag_name) {
try {
flags.add(Enum.valueOf(enumClass, flag_name));
}
catch (Exception e) {}
}
public boolean on(String flag_name) {
try {
return flags.contains(Enum.valueOf(enumClass, flag_name));
}
catch (Exception e) {
return false;
}
}
}
class SampleUsage {
enum DiagBits {
zero, one, two, three;
}
public static final Diagnostic<DiagBits> diag = new Diagnostic<>(DiagBits.class);
public SampleUsage() {}
void doStuff() {
if (diag.on(DiagBits.three))
showDebugInfo();
if (diag.on("three"))
showDebugInfo();
}
private void showDebugInfo() {}
}

Getting Enum from an integer having a Class<? extends Enum> object

I have seen this which is pretty nice solution if i had a string instead of integer, but in case all i have is the specific enum's class object and an integer, how to do i get the specific enum constant instance?
Relying on the ordinal value of Java enum constants is poor practice -- it's too easy to accidentally reorder them, which would then break your code. The better solution is to simply provide your own integer that you can use instead:
public enum MyThing {
FOO(1),
BAR(2),
BAZ(3);
private final int thingId;
private MyThing(int thingId) {
this.thingId = thingId;
}
public int getThingId() {
return thingId;
}
}
Then whenever you want to get the thingId from a MyThing, just call the getThingId() method:
void doSomething(MyThing thing) {
System.out.printf("Got MyThing object %s with ID %d\n",
thing.name(), thing.getThingId());
}
If you want to be able to look up a MyThing by its thingId, you can build a lookup table yourself and store it in a static final field:
private static final Map<Integer, MyThing> LOOKUP
= createLookupMap();
private static Map<Integer, MyThing> createLookupMap() {
Map<Integer, MyThing> lookupMap = new HashMap<>();
for (MyThing thing : MyThing.values()) {
lookupMap.put(thing.getThingId(), thing);
}
return Collections.unmodifiableMap(lookupMap);
}
public static MyThing getThingById(int thingId) {
MyThing result = LOOKUP.get(thingId);
if (result == null) {
throw new IllegalArgumentException(
"This is not a valid thingId: " + thingId);
}
return result;
}
If you end up having a lot of enum classes and you want to do a similar thing with each of them, you can define an interface for that:
public interface Identifiable {
int getId();
}
And then make your enum implement that interface:
public enum MyThing implements Identifiable {
...
#Override
public int getId() {
return thingId;
}
}
And then you could build a reusable mechanism for looking up an Identifiable object based on its ID.
seem to have found the answer :
((Class<? extends Enum>)clazz).getEnumConstants()[index]
although for any-one looking for that, you should consider following #Daniel Pryden answer as most likely that using this in most use cases i can think of is bad practice.

Can the compiler verify a generic type of an object through a generic method?

First of all, sorry for the bad title. I don't know how to describe the problem in a few words (maybe not even in many)...
I am refactoring some settings in our system to be more abstract. The current solution has multiple tables in the DB, one for each settings area. In order to add a new setting, you'll need to extend the schema, the hibernate class, all transfer object classes, getters/setters, etc. I felt that this is violating OCP (open-closed principle), thus the refactoring.
I've spent some time coming up with ideas on how to implement such an abstraction. My favourite idea so far is the following:
1 enum for each settings area
1 enum value for each setting
Each setting is a SettingsDefinition<T> class using a generic type
A SettingsService is using static get/set methods with generic types
So for example, a settings area could be:
public enum SettingsABC{
A(new SettingDefinition<Integer>("A", 123)),
B(new SettingDefinition<String>("B", "Hello")),
C(new SettingDefinition<Boolean>("C", false));
private SettingDefinition settingDefinition;
SettingsABC(SettingDefinition settingDefinition) {
this.settingDefinition = settingDefinition;
}
public SettingDefinition getDefinition() {
return settingDefinition;
}
}
Where the SettingDefinition is the following:
public class SettingDefinition<T> {
private String name;
private T defaultValue;
public SettingDefinition(String name, T defaultValue) {
this.name = name;
this.defaultValue = defaultValue;
}
public String getName() {
return name;
}
public T getDefaultValue() {
return defaultValue;
}
}
And the service to get/set the values would be:
public class SettingsService {
public static <T> T getSetting(SettingDefinition setting) {
// hit db to read
// return value
}
public static <T> void setSetting(SettingDefinition setting, T value) {
// hit db to write
}
}
And the consumer would look something like this:
String value = SettingsService.getSetting(SettingsABC.B.getDefinition());
SettingsService.setSetting(SettingsABC.A.getDefinition(), 123);
My problem is that I cannot enforce a compiler type check between the generic type of the SettingDefinition inside SettingsABC and the generic type of get/set methods of the service. So in essence, I can do this:
Integer value = SettingsService.getSetting(SettingsABC.B.getDefinition());
Where B's definition is of type String.
Also, I can do this:
SettingsService.setSetting(SettingsABC.A.getDefinition(), "A");
Where A's definition is an Integer.
Is there any way to use generics to force these two different generic types match?
You can convert the enum to the class:
public final class SettingsABC<T> {
public static final SettingsABC<Integer> A =
new SettingsABC<>(new SettingDefinition<>("A", 123));
public static final SettingsABC<String> B =
new SettingsABC<>(new SettingDefinition<>("B", "Hello"));
public static final SettingsABC<Boolean> C =
new SettingsABC<>(new SettingDefinition<>("C", false));
private final SettingDefinition<T> settingDefinition;
// private constructor, so nobody else would instantiate it
private SettingsABC(SettingDefinition<T> settingDefinition) {
this.settingDefinition = settingDefinition;
}
public SettingDefinition<T> getDefinition() {
return settingDefinition;
}
}
This way individual constants will be typed. Now you can use the type arguments for SettingService as well:
public static <T> T getSetting(SettingDefinition<T> setting) {
...
}
public static <T> void setSetting(SettingDefinition<T> setting, T value) {
...
}
Although it's not an enum anymore, it can be used mostly in the same way. If you need other methods which are usually available in enum, you can mimic them like this:
public String name() {
return settingDefinition.getName();
}
#Override
public String toString() {
return settingDefinition.getName();
}
// and so on

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

Complicate generics in Java

I have one supertype defined as:
public abstract class AType<T> {
....
private T value;
private T mask;
public T getValue() {
if (isMasking())
return null;
return this.value;
}
public void setValue(T value) {
if (value == null)
throw new IllegalArgumentException("Value is mandatory.");
this.value = value;
}
protected T getMask() {
if (!isMasking())
return null;
return this.mask;
}
protected void setMask(T mask) {
if (mask == null)
throw new IllegalArgumentException("Mask is mandatory.");
this.setMasking(true);
this.mask = mask;
}
...
}
and few subtypes like:
public class SpecType extends AType<Integer> {
...
}
these sub types specifies the unknown parameter.... i have more f.e. IPv4, Long, and so on
now i need to somehow in runtime do a dynamic cast...
i have these classes defined in enum like this:
public enum Type {
SOME_TYPE(new TypeID(0, (short) 0), OFMU16.class,
new Instantiable<AType<?>>() {
#Override
public SpecType instantiate() {
return new SpecType(new OFMatchTypeIdentifier(0, (short) 0));
}
}),...;
...
public Class<? extends AType<?>> toClass() {
return this.clazz;
}
...
}
I want do something like:
AType<?> type = SOME_TYPE.newInstance(); //this works
SOME_TYPE.toClass().cast(type).setValue(10); //this don't work
so I have to do it statically:
((SpecType) type).setValue(10);
Everything would be OK, but the user of this module will not want to look in enum and cast manually every time. This will probably make mistakes and spend a lot of time with debugging :/....
My question is how can I refactor this or how do I define structure of inheritance to allow user to cast dynamically? Is it possible?
Edit:
I am parsing packets from network. There is a lot types which differs in Vendor Type identifier and type of Value/Mask - these fields are all constant for every this combination, so i has defined it as enum constants. F.e. 20 have different only TypeID but same VendorID and all of them can be represented as Integer, next 10 differ in VendorID And TypeID but all of them can be represented as Short and so on.
It's still not clear why you should have to cast at all. As soon as SOME_TYPE is written into your sourcecode OR the type of set setValue method is hardcoded (in your example int or Integer) you don't need runtime checking - you need compile time checking.
So I suppose the following snippet is how your API users should code:
public class TypeTest {
public static void main(String[] args) {
AType<Integer> type0 = Types.SOME_TYPE_0.instantiate();
type0.setValue(10);
AType<String> type1 = Types.SOME_TYPE_1.instantiate();
type1.setValue("foo");
}
}
I have stripped down your example to the bare minimum which is required to understand the Generics part:
abstract class AType<T> {
private T value;
// standard getter/setter
public T getValue() { return this.value; }
public void setValue(T value) { this.value = value; }
}
class SpecTypeInt extends AType<Integer> {
}
class SpecTypeString extends AType<String> {
}
interface Instantiable<T> {
T instantiate();
}
The key part is: Don't use an enum, because an enum cannot have type parameters. You can use a plain interface instead like the next snippet. Each reference in the interface points to a factory. Each factory knows a) the abstract type and b) the concrete type. To make Generics happy you have to glue a) and b) together with ? extends X.
interface Types {
Instantiable<? extends AType<Integer>> SOME_TYPE_0 = new Instantiable<SpecTypeInt>() {
#Override
public SpecTypeInt instantiate() {
return new SpecTypeInt();
}
};
Instantiable<? extends AType<String>> SOME_TYPE_1 = new Instantiable<SpecTypeString>() {
#Override
public SpecTypeString instantiate() {
return new SpecTypeString();
}
} ;
}
Cleanup: Must your user look into the interface: Yes, he must in any case, because he must know which is the appropriate type for setValue 1. NO solution can circumvent this. Although Eclipse might help you and your users a little bit: In main just type Types.SOME_TYPE_1.instantiate(); then go to the start of the line, hit Ctrl2 + L ("Assign to loccal variable") and Eclipse replaces the AType<String> instantiate = part for you.
1If your users don't know the right type for the setValue method, then you are asking the wrong question. In that case you should have asked something like "How to design a Generic safe conversion facility?".
Maybe using a setValue method like this:
public void setValue(Object value) {
if (value == null)
throw new IllegalArgumentException("Value is mandatory.");
this.value = (T)value;
}
Although you will have an unchecked cast.
Hope this helps

Categories

Resources