Emulate C++ enum integer with Java Enums - java

I'm attempting to translate some C++ code into Java. I'm looking for the best way to emulate this type of C++ paradigm in Java -- I think enums are probably the answer but I'm open to anything
C++ code:
typedef UInt32 Type;
enum { UNKNOWN, QUIT, SYSTEM, TIMER, LAST }
...
Type newType = UNKNOWN;
Type nextType = LAST + 1;
...
// "Register" the new type
newType = nextType;
nextType++;
...
switch (newType) {
case UNKNOWN:
case QUIT:
...
case LAST:
// Ignore unset or predefined types
default:
// Some type other than the predefined. Do something special
Essentially I'm looking for a way to "expand" the values of a Java enumeration.
enum Type { UNKNOWN, QUIT, SYSTEM, TIMER, LAST }
doesn't quit cut it.
I like the idea of making a new object for strong typing.
Again, I'm looking for the best pattern to use here. I could easily float by with a few public static final int UNKNOWN, etc

One advantage of Java enums is, that they are essentially objects like all others. In particular, you can have methods on the constants, and make your enum implement interfaces:
interface Useful {
void doStuff();
}
enum Foo implements Useful {
DEFAULT {
public void doStuff() {
...
}
},
MAGIC {
public void doStuff() {
...
}
}
}
So, instead of taking arguments of the enum type, your methods could accept any implementation of the interface, and in particular, provide the default stuff by having the enum constants implement whatever is necessary.
They can also have members:
enum Explicit {
FIRST(0), SECOND(1), THIRD(2);
private final int value;
private Explicit(int v) {
this.value = v;
}
}
Note, that constants have an internal numeric value (reflecting the position of the constant among its peers) which is accessible using the ordinal method:
assert Explicit.FIRST.ordinal() == 0;
But relying on this is a little bit dangerous. If you are going to (say) persist enum constants in a database, then the following change would break the code:
enum Explicit {
FIRST(0), NEWELT(-1), SECOND(1), THIRD(2);
private final int value;
private Explicit(int v) {
this.value = v;
}
}
when using ordinal values. For this reason, the serialization machinery uses the constant's name instead of its position when serializing enum values.
So:
Type.X + 1
would be
Enum.values()[Enum.X.ordinal() + 1]
and the switch could be modelled using interfaces implemented by the enum itself (you can use enums in switch statements in Java, but often, making the enum implement the necessary code yields more maintainable code)

If each value of Type is just an int, then I'd probably go for a bunch of static final ints in a class.
Just for the record, something like this works more or less type-safely. I can't determine if the complexity is warranted without knowing more about the problem.
public class abstract Type
{
public static final Type UNKNOWN = registerStd("UNKNOWN");
...
public static final Type TIMER = registerStd("TIMER");
// use this to keep track of all the types
private static final List<Type> REGISTERED = ...
//This will do your switch statement for you, implemented by
// anonymous subclasses
public abstract void dispatch(Type onMe);
// here's how you make the standard ones
private static Type registerStd(String name)
{
Type heresOne = new Type(name)
{
// note, it's a no-op
public void dispatch(DoStuffer algorithm) {}
};
REGISTERED.add(heresOne);
return heresOne;
}
//here's how you make the non-standard ones
public static Type registerNew(String name)
{
Type heresOne = new Type(name)
{
public void dispatch(DoStuffer algorithm) {algorithm.execute(this)}
};
REGISTERED.add(heresOne);
return heresOne;
}
}
public interface DoStuffer
{
public void execute(Type onMe);
}
//Then your code becomes
Type newType = Type.registerNew("NewType");
newType.dispatch
(
new DoStuffer()
{
public void algorithm(Type forMe) { ... }
}
);
Maybe this is a little esoteric. But it does allow for "easy dispatch" at the caller site and an extensible enum, in some sense.

Related

Is there some sort of generic bound in Java?

I am defining a type Option<T> in Java that should behave as much as possible as Rust's equivalent.
It has a method, Option::flatten, that is only implemented if the inner T is some other Option<T>. I am thinking of something like this:
public class Option<T> {
/* fields, constructors, other methods */
#Bound(T=Option<U>)
public <U> Option<U> flatten() {
if (isNone()) return None();
else return this.unwrap();
}
}
But the syntax is of course completely fictional. Is there some way to make this work in Java? I know static methods are an option, but they can't be called like a normal method which is the only goal of this type.
This is not supposed to be a standalone thing, but rather a part of a larger Java implementation of Rust iterators I'm currently working on.
The problem with trying to come up with a non-static method such as flatten is that in Java one cannot conditionally add more methods to a class based on whether the type parameter of the class fulfills a certain constraint.
You can, however, make it a static method and constrain its arguments to whatever you need.
class Option<T> {
// ...
public static <U> Option<U> flatten(Option<Option<U>> option) {
if (option.isNone()) return None();
return option.unwrap();
}
}
Which would work for valid implementations of None, isNone and unwrap.
A more complete example follows.
public static class Option<T> {
private final T value;
private Option(T x) {
this.value = x;
}
public static <T> Option<T> of(T x) {
java.util.Objects.requireNonNull(x);
return new Option<>(x);
}
public static <T> Option<T> None() {
return new Option<>(null);
}
public T unwrap() {
java.util.Objects.requireNonNull(this.value);
return this.value;
}
public boolean isNone() {
return this.value == null;
}
public static <U> Option<U> flatten(Option<Option<U>> option) {
if (option.isNone()) return Option.None();
return option.unwrap();
}
#Override
public String toString() {
if (this.isNone()) {
return "None";
}
return "Some(" + this.value.toString() + ")";
}
}
Usage:
var myOption = Option.of(Option.of(5));
System.out.println("Option: " + myOption);
System.out.println("Flattened: " + Option.flatten(myOption));
Output:
Option: Some(Some(5))
Flattened: Some(5)
I think the way you want to handle this is not to actually have a flatten() method, but have different handling in your constructor. Upon being created, the constructor should check the type it was handed. If that type is Option, it should try and unwrap that option, and set its internal value to the same as the option it was handed.
Otherwise, there isn't really a way for an object to 'flatten' itself, because it would have to change the type it was bounded over in the base case. You could return a new object from a static method, but are otherwise stuck.
I want to point out some of the potential headaches and issues regarding this re-implementation of Optional<T>.
Here's how I would initially go about it:
public class Option<T> {
/* fields, constructors, other methods */
public <U> Option<U> flatten() {
if (isNone()) return None();
T unwrapped = this.unwrap();
if (unwrapped instanceof Option) {
return (Option<U>) unwrapped; //No type safety!
} else {
return (Option<U>) this;
}
}
}
However, this code is EVIL. Note the signature of <U> Option<U> flatten() means that the U is going to be type-inferenced into whatever it needs to be, not whatever a potential nested type is. So now, this is allowed:
Option<Option<Integer>> opt = /* some opt */;
Option<String> bad = opt.flatten();
Option<Option<?>> worse = opt.<Option<?>>flatten();
You will face a CCE upon using this for the other operations, but it allows a type of failure which I would say is dangerous at best. Note that any Optional<Optional<T>> can have #flatMap unwrap for you: someOpt.flatMap(Function.identity());, however this again begs the question of what caused you to arrive at a wrapped optional to begin with.
Another answer (by #NathanielFord) notes the constructor as an option, which seems viable as well, but will still face the runtime check upon construction (with it simply being moved to the constructor):
public class Option<T> {
/* fields, constructors, other methods */
public Option<T>(T someValue) { ... }
public Option<T>(Option<T> wrapped) {
this(wrapped.isNone() ? EMPTY_OBJECT : wrapped.unwrap());
}
public Option<T> flatten() {
return this; //we're always flattened!
}
}
Note as well, the re-creation of Optional<T> by
#E_net4thecommentflagger has the potential for a nasty future bug: Optional.ofNullable(null).isNone() would return true! This may not be what you want for some potential use-cases, and should #equals be implemented in a similar manner, you'd end up with Optional.ofNullable(null).equals(Optional.None()), which seems very counter-intuitive.
All of this to say, that while Rust may require you to deal with these nested optionals, you are writing code for Java, and many of the potential restrictions you faced before have changed.

How to work-around the restriction of primitive objects - like Integer, String - not being allowed to derive from?

I realize that it is not possible to derive from primitive objects as they are declared final. How do I work around this restriction? I am programming with the JPA Criteria API. Almost everywhere I handle with my own methods having Integer/String parameters to compare against entity fields representing database table row values. On any of these parameters I would like to accept QueryParameter<Integer> or QueryParameter<String>. Doing so I would have to create the method a second time accepting query parameters instead of the literals. However, thinking about value lists (as in the QueryBuilder's in(...) method) with permutating literals and query parameters, makes it hard or even impossible to implement.
Let us assume I had an entity Car with a method withFeatures(StringRepresentation ... features) and there would be literals and query parameters had derived from the same super-class StringRepresentation which itself would have be derived from the primitive type String. I would like to do so:
myCar.withFeatures("Seat Heating", "Metallic Color", "Trailer Hitch");
myCar.withFeatures(new QueryParam<String>("MyFavourit"));
myCar.withFeatures("Seat Heating", new QueryParam<String>("LoveThatColor"), "Trailer Hitch");
Has anyone an approach or even kind of a solution for this?
I'd use a builder pattern with one method for each type of criterion.
class Car {
private Set<String> features = new HashSet();
public Car withFeature(String f) {
features.add(f);
return this;
}
public Car withFeature(QueryParameter<String> q) {
features.add(q.getStringRepresentation()); // or whatever
return this;
}
...
}
So you can say:
myCar.withFeature("Seat Heating")
.withFeature(new QueryParam<String>("MyFavourit");
with permutating literals and query parameters, makes it hard or even impossible to implement
You could leverage CharSequence for strings, but I'm not sure that's a god idea...
import lombok.RequiredArgsConstructor;
public class Test {
public static void main(String[] args) {
withFeatures("test", new StringQueryParam("test2"));
}
#SafeVarargs
public final static <T extends CharSequence> void withFeatures(T ...params) {
// Wrap in StringQueryParam if not an instance of QueryParam<String>
}
interface QueryParam<T> {
}
#RequiredArgsConstructor
static class StringQueryParam implements QueryParam<String>, CharSequence {
private final CharSequence value;
#Override
public int length() {
return value.length();
}
#Override
public char charAt(int index) {
return value.charAt(index);
}
#Override
public CharSequence subSequence(int start, int end) {
return value.subSequence(start, end);
}
}
}
Having less verbose static factory methods (e.g. QueryParam.of, QueryParam.all, etc. for query params) mixed with builders or ways to combine them effectively could help.
e.g.
// Assuming Lists.union util method
withFeatures(Lists.union(
QueryParam.all("a", "b"),
QueryParam.of("c")
));
// With static imports
withFeatures(union(params("a", "b"), param("c"));
// With ParamsBuilder
withFeatures(ParamsBuilder.of("a", "b").add(QueryParam.of("c").build())));
Hopefully that gives you some ideas on how to design the API! You may as well use a more complicated, but flexible route where the entire criteria is just an AST so that QueryParam really just is a type of Expression in the AST allowing to create composites, etc. If you look at QueryDSL everything is a DslExpression and you have visitors to execute operations against the tree.
I spent some time to solve that problem taking in the hints from the Java Community so far.
Of course I am a follower of Java's concept of type safety (thanks to plalx). Hence, my solution will probably has to do with parameterized types.
And also I do admiring the concept of design patterns like many others (thanks to tgdavies). Hence, I use the builder pattern with one method for each type of criterion. I will accept to implement car feature methods for
using plain old literals of String
as well as specifying parameters of String
That is:
myCar.withFeatures("Seat Heating", "Metallic Color", "Trailer Hitch");
as well as specifying (let's say) query parameters or String parameters of some kind with a slightly more complex way by using a static method sp(...)
myCar.withFeatures(sp("MyFavourit"));
and of course a mixture of both, introducing another static method sr(...) for string representation:
myCar.withFeatures(sr("Seat Heating"), sp("LoveThatColor"), sr("Trailer Hitch"));
The mixture of both is important in cases where we want to use variable arguments in method signatures to specify those representations, in this case car features.
As one can see, it is almost the usage I stated above when posting this question.
How can I achieve this?
At first I designed an interface to implement my different String representations against:
public interface ValueTypeRepresentation<T> {
public Class<T> getClazz();
public QueryParameter<T> getQueryParameter();
public RepresentationType getRepresentationType();
public T getValue();
}
The methods are to determine whether the representation is a literal or a parameter, and to get the literal's value resp. the parameter itself to later on use its name.
The clazz member is to ease the Java Generic Type Inference purposes because I will be using parameterized types to implement different type representations. As I said, String ist just the starter of the show.
Then I designed an abstract class to derive the concrete classes of representations of different primitive objects from:
abstract class AbstractValueTypeRepresentation<T> implements ValueTypeRepresentation<T> {
private Class<T> clazz;
private RepresentationType representationType = RepresentationType.VALUE;
private QueryParameter<T> queryParameter;
private T value;
public AbstractValueTypeRepresentation(Class<T> clazz, T value) {
this.clazz = clazz;
this.representationType = RepresentationType.VALUE;
this.value = value;
}
public AbstractValueTypeRepresentation(QueryParameter<T> qp) {
this.clazz = qp.getClazz();
this.representationType = RepresentationType.PARAM;
this.queryParameter = qp;
}
#Override
public Class<T> getClazz() {
return clazz;
}
#Override
public QueryParameter<T> getQueryParameter() {
return queryParameter;
}
#Override
public RepresentationType getRepresentationType() {
return representationType;
}
#Override
public T getValue() {
return value;
}
}
To distinguish a literal of that type from the query parameter of that type, I introduced this enumeration:
public enum RepresentationType {
PARAM, VALUE;
}
Then I designed the first concrete representation, here for my StringRepresentation (derived from the abstract class above):
public class StringRepresentation extends AbstractValueTypeRepresentation<String> {
public static StringRepresentation sr(String s) {
return new StringRepresentation(s);
}
public static StringRepresentation sp(String name) {
return new StringRepresentation(new QueryParameter<String>(String.class, name));
}
public StringRepresentation(String value) {
super(String.class, value);
}
public StringRepresentation(QueryParameter<String> queryParameter) {
super(queryParameter);
}
}
Obviously this is easy to extend to representations of Integer, Float, LocalDate, etc.

Extend a Java Enum with additional functions

I have an enum from a common Library (it cannot be changed) as a field from a Class.
I need to use that enum values as a switch-case in order to do something accordingly (for example save some data to a database).
This is for a Java 11 micro-service using Spring as a framework.
What I did before knowing the enum has to stay immutable, I avoided an ugly switch case with an overridden abstract function inside the enum like this:
public enum InvoiceStatus {
DRAFT {
#Override public void action(InputMessage inputMessage) {
invoiceFileService.draft(inputMessage);
}
},
VALID {
#Override public void action(InputMessage inputMessage) {
invoiceFileService.valid(eiInvoiceFileMessage);
}
},
NOT_VALID {
#Override public void action(InputMessage inputMessage) {
invoiceFileService.notValid(eiInvoiceFileMessage);
}
};
//+20 more values...
#Autowired
InvoiceFileService invoiceFileService;
public abstract void action(InputMessage inputMessage);
}
and I simply called the enum like this, so with different values from the enum the called function from the service would be different without writing a long switch-case.
invoice.getStatus().action(inputMessage);
Now the new requirement needs the enum to live inside a common library so it can refer to InvoiceFileService class which will be only local to my project.
I tried different options like HashMaps but the code went ugly and un-maintainable.
Is there a clean way to extend the simple enum (with only values definition) and add to it the abstract function to do stuff? maybe java 8 added some new way to do this.
You could create a wrapper enum.
public enum WrappedInvoiceStatus {
DRAFT(InvoiceStatus.DRAFT, this::someAction),
// other values
private WrappedInvoiceStatus(InvoiceStatus status, Action action) {
this.status = status;
this.action = action;
}
private interface Action { // can be one of Java default functional interfaces as well
void doSomething(InputMessage msg);
}
private void someAction(InputMessage msg) {
// behavior
}
// some plumbing required
}
Basically I’m suggesting using wrapping and lambda expressions or method references. The world of functional programming takes some getting used to. Not everyone is a fan. Your mileage may vary.
As others already said, you can not extend the enum at runtime.
But an enum can implement an interface.
So the basic idea is:
You make an interface with the action as sole abstract method:
public interface InvoiceAction {
void action(InputMessage message);
}
Your enum implements that interface
public enum InvoiceStatus implements InvoiceAction {
// ... no other changes needed
}
In all the cases where you only need to use the actual action, change InvoiceStatus to InvoiceAction. This is the most risky change. Make sure to recompile all code.
Because InvoiceAction only has one abstract method, it's a functional interface, and can be implemented with a lambda expression:
invoice.setStatus(msg -> ...);
This change is probably the most invasive change, but it might be the right thing to do - if you need a different action next time, you won't have the same problem as today.
Enum type is not extendable and implicitly final as specified in JLS:-
An enum declaration is implicitly final unless it contains at least one enum constant that has a class body (§8.9.1).
Hence a class could not extends an enum type. However you could use wrapper or adapter pattern to add additional behaviours/fields of the enum. For example:-
#Service
public class SimpleInvoiceFileService implements InvoiceFileService{
private final InvoiceStatus invoiceStatus;
public SimpleInvoiceFileService(InvoiceStatus status){
invoiceStatus = status;
}
#Override
public void draft(InputMessage input){
this.invoiceStatus.action(input);
}
#Override
public void valid(InputMessage input){
this.invoiceStatus.action(input);
}
// Add more methods to InvoiceFileService interface
// as required and override them here.
}
JLS Reference:-
https://docs.oracle.com/javase/specs/jls/se11/html/jls-8.html#jls-8.9

Change an object's implemented interfaces at runtime

Is it possible to dynamically add to the list of interfaces implemented by an object (such that instanceof returns true and casts don't fail)?
I have a set of objects whose types need to change dynamically during runtime. As their state changes, more of their methods/properties become valid. Currently, this is done in a "brute-force" way... all members are exposed, and calling the wrong one at the wrong time is a bug. Ideally, I would like to use static typing, and to pass these objects to methods which expect specific interfaces. The set of interfaces that an object implements will only increase, so old references would remain valid.
Is it possible to change an object's implemented interfaces at runtime, either using built-in reflection or via third-party bytecode manipulation?
You can use a Proxy but as the comments suggest - this is almost always not the best option.
You would be better to craft you object as multifaceted.
interface Interface1 {
String getI1();
}
interface Interface2 {
String getI2();
}
class Multifaceted {
String i1;
String i2;
private final Interface1 asInterface1 = new Interface1() {
#Override
public String getI1() {
return i1;
}
};
private final Interface2 asInterface2 = new Interface2() {
#Override
public String getI2() {
return i2;
}
};
public Interface1 asInterface1() {
if ( i1 == null ) {
throw new InvalidStateException("I am not ready to be one of these yet!");
}
return asInterface1;
}
public Interface2 asInterface2() {
return asInterface2;
}
}

Can I declare enums within enums to specify/limit both keys and values in a map in Java?

I want to be able to specify a list of keys and allowed values for each key programatically so that the code can be checked at compile time for errors and in the hope of better performance.
Imagine I am representing word in a database and each word has a number of features:
public class Word {
public Map<Feature, FeatureValue> features = new EnumMap<Feature, FeatureValue>();
}
And I have an enum class:
public enum Feature {
TYPE("Type") {
enum Value {
NOUN("Noun"),
VERB("Verb");
}
#Override
public Value[] getValues() {
return new Value[]{Value.NOUN, Value.VERB};
}
},
PLURALITY("Plurality") {
enum Value {
SING("Singular"),
PL("Plural");
}
#Override
public Value[] getValues() {
return new Value[]{Value.SING, Value.PL};
}
},
}
I would at least want to be able to do something like:
word.features.put(TYPE, TYPE.Value.NOUN);
word.features.put(PLURALITY, PLURALITY.Value.PL);
So that it's easy to see that the values match the key, but the enum within enum syntax doesn't seem to be allowed.
I also tried this:
TYPE("Type") {
public String NOUN = "Noun";
public String VERB = "Verb";
but I couldn't reference TYPE.NOUN since they aren't allowed to be static for some reason.
Please is there someone who know a good pattern to specifying something like this? I'm just worried if use strings in my code like
word.features.put(TYPE, "Noun");
I am asking for trouble with typos etc.
You can't do it like that but you can do it like this:
// define a type values as an enum:
enum TypeValue {
Noun, Verb
}
// define an attribute class parametrized by an enum:
public class Attribute<E extends Enum<E>> {
// define your attribute types as static fields inside this class
public static Attribute<TypeValue> Type = new Attribute<TypeValue>();
}
// and now define your method like this:
<E extends Enum<E>, Feature extends Attribute<E>> void put(Feature feature, E value) {
}
// you will then have a compilation error when trying to invoke the method with improper associated parameters.
// eg if we define
enum OtherValue { X }
features.put(Attribute.Type, TypeValue.Noun); // ok
features.put(Attribute.Type, OtherValue.X); // Fails

Categories

Resources