I have an enum that looks like
public enum MyEnum
{
myValue
{
#Override
public String myMethod(String dostuff)
{
return dostuff + "One";
}
},
myOtherValue
{
#Override
public String myMethod(String dostuff)
{
return dostuff + "Two";
}
},
aThirdValue
{
#Override
public String myMethod(String dostuff)
{
return dostuff + "Three";
}
};
public abstract String myMethod(String dostuff);
}
Now I think we can all agree that this looks horrible?
but what would be the bether way? I could have an abstractfactory, but then i would need three implementationclasses that each as a one line method. Dont find that so pretty either. I could use a switch (either in the code or in the enum). But then i could forgett to add a case.
So, whats the way to go? There must be a pattern for this, but cant seem to find one.
The best ive come up with so far is to add comments to autocollapse the methods in Netbeans, not so brilliant that either.
The solution is to create a private constructor for the enum:
public enum MyEnum
{
myValue("One"), myOtherValue("Two"), aThirdValue("Three");
private String value;
private MyEnum(String value) { this.value = value; }
public String myMethod(String dostuff)
{
return dostuff + value;
}
}
[EDIT] Note that you can pass more complex things in. For example, you can pass in a class which implements a certain interface (say Work which has a method doWork()). This way, you can store method calls in enums to do different kinds of work.
Check out the command pattern or maybe the strategy pattern.
It's ugly, but most solutions to non-trivial extensions of the problem are just going to move the ugliness around.
For instance, you could encapsulate the three different behaviors in three different implementations of some interface, and then pass a different behavior implementation to the constructor of each enum. (This is basically the command or strategy approach that others are suggesting).
If you make these implementations, and the interface, separate classes, then you've potentially exposed that behavior beyond the enum, which is unnecessary and arguably ugly.
If you make them private static inner classes of the enum, you've moved the ugliness from the top of the file to the bottom of the file. How much less ugly this is is in the eye of the beholder.
public enum Foo {
ONE(new OneDelegate()),
TWO(new TwoDelegate()),
THREE(new ThreeDelegate());
// ////////////////////
// Private stuff
private final FooDelegate delegate;
private Foo(FooDelegate delegate) {
this.delegate = delegate;
}
// ////////////////////
// Public methods
public String doStuff(String stuff) {
return delegate.doStuff(stuff);
}
// ////////////////////
// Helper classes
private static interface FooDelegate {
String doStuff(String stuff);
}
private static class OneDelegate implements FooDelegate {
#Override
public String doStuff(String stuff) {
return "One " + stuff;
}
}
private static class TwoDelegate implements FooDelegate {
#Override
public String doStuff(String stuff) {
return "Two " + stuff;
}
}
private static class ThreeDelegate implements FooDelegate {
#Override
public String doStuff(String stuff) {
return "Three " + stuff;
}
}
}
The other obvious solution is to put all three behaviors in as private methods, and put a switch(this) in the public method. Personally, I think this is ugly as sin, but a lot of ex-C programmers seem to like it. :)
public enum Foo {
ONE, TWO, THREE;
// ////////////////////
// Public methods
public String doStuff(String stuff) {
switch(this) {
case ONE:
return doStuffOne(stuff);
case TWO:
return doStuffTwo(stuff);
case THREE:
return doStuffThree(stuff);
// If we're handing all enum cases, we shouldn't need
// a default (and per comments below, if we leave out
// the default, we get the advantage that the compiler
// will catch it if we add a new enum value but forget
// to add the corresponding doStuff() handler
// default:
// throw new IllegalStateException("Who am I?");
}
}
// ////////////////////
// Static helpers
private static String doStuffOne(String stuff) {
return "One " + stuff;
}
private static String doStuffTwo(String stuff) {
return "Two " + stuff;
}
private static String doStuffThree(String stuff) {
return "Three " + stuff;
}
}
What about?
public enum MyEnum {
myValue("One"),
myOtherValue("Two"),
aThirdValue("Three");
private final String postfix;
private MyEnum(String postfix) {
this.postfix )= postfix;
}
public String myMethod(String dostuff) {
return dostuff + postfix;
}
}
Even if your real stuff is more complex, there are several techniques that allow such improvements. Please post your real need...
Related
Lets say I have a class to model an item in a game like so:
public class Item {
private final EnumItem type;
public Item(EnumItem type) {
this.type = type;
}
public Item(String name) {
this.type = EnumItem.fromName(name);
}
}
public enum EnumItem {
MACHINE_GUN("machine_gun"),
SWORD("sword"),
BAT("bat"),
DEFAULT("default");
private final String name;
public EnumItem(name) {
this.name = name;
}
public String getName() { return name; }
public static EnumItem fromName(String name) {
for(EnumItem i: EnumItem.values()) {
if(i.name.equals(name)) {
return i;
} else {
return EnumItem.DEFAULT;
}
}
}
}
Assume that .equals() and .hashCode() of Item are overridden correctly to compare the internal Enum.
Now I want a way to distinguish these items with a getter in Item: should I return an Enum or the String name? Is it good practice to return an Enum in general? Or is there a better way to distinguish these Items? Because returning the enum kind of looks like exposing the rep to me and I don't want my colleagues to use EnumItem directly to compare Items.
The approaches I thought of are the following:
string getName() to do something like item1.getName().equals("machine_gun");
EnumItem getEnum() to do item1.getEnum().equals(EnumItem.MACHINE_GUN);
item1.equals(new Item("machine_gun"));
static name(String name) { new Item(name) } to do item1.equals(Item.name("machine_gun"));
I don't know what should I do, I'd appreciate some insight from experienced programmers.
I know they look like they would from context, but in my use case these items have no special functionality that would justify extending from the base Item class.
Is this good practice? Sure, you're using aggregation since Item doesn't depend on EnumItem, which is fine. That being said, could it be done better? Sure. Is the alternative I provide the only solution? No.
Alternative
If you want this to be extensible, consider using an interface to represent an item. Then allow the interface to extend this interface to provide some standard types. Alternatively you could use composition or aggregation to define a type inside EnumItem that implements the Item interface to ensure that equals/hashcode for the Item are always override and adhere to some contract.
interface Item {
String key();
}
enum EnumItem implement Item {
private final String key;
EnumItem(String key) {
this.key = key;
}
#Override
public String key() {
return key;
}
}
class AbstractItem implements Item {
// constructor, override name()
}
Item item = EnumItem.FOO_BAR;
Item item2 = new AbstractItem("FooBar");
Item item3 = () -> "FooBar";
I have a class with some 20+ fields of the same type that are populated during different stages of the object lifecycle.
One of the class methods should return the field value based on the field name.
So far I have something like this:
public String getFieldValue(String fieldName){
switch (fieldName.toLowerCase(){
case "id": return getId();
case "name": return getName();
.....
the problem with this is high cyclomatic complexity.
What would be the easiest way to tackle this?
Edit: Thanks to #Filippo Possenti for his comment
Instead of a switch, you can use a Map.
Here is an example.
static interface C {
String getA();
String getB();
String getC();
}
#FunctionalInterface
static interface FieldGetter {
String get(C c);
}
static Map<String, FieldGetter> fields = Map.of(
"a", C::getA,
"b", C::getB,
"c", C::getC
);
static String getField(C object, String fieldNameToRetrieve) {
var getter = fields.get(fieldNameToRetrieve);
if(getter == null) {
throw new IllegalArgumentException("unknown field");
}
return getter.get(object);
}
Why don't you use reflexion or an existing library for this ? (Or why do you even have this kind of method)
In theory you could reduce the getFieldValue() method complexity by:
storing the getter method reference as Producer<?> in Map<String, Producer<?>>
using reflection to lookup fields
using 3rd party library that supports querying the bean by property name e.g. commons-beanutils.
Each of these approaches will however increase the getFieldValue() method complexity and potentially reduce the performance. Both are worse problems than high complexity.
It feels like you should review why you need the getFieldValue() method in the first place, maybe it should be a Map<String, ?>?
Assuming that the fieldName possible values match the getters on the bean, you can use Apache's BeanUtils:
https://commons.apache.org/proper/commons-beanutils/apidocs/org/apache/commons/beanutils/PropertyUtils.html#getSimpleProperty-java.lang.Object-java.lang.String-
Basically, you could do something like this:
public String getFieldValue(String fieldName){
return PropertyUtils.getSimpleProperty(fieldName.toLowerCase());
}
This is more about improving code readability than improving cyclomatic complexity so if it's pure performance what you're after, this may not be your solution.
If pure performance is what you're after, you could try and leverage lambdas and a Map.
import java.util.Map;
import java.util.HashMap;
import java.util.function.Function;
public class HelloWorld{
public static class MyClass {
private static Map<String, Function<MyClass, Object>> descriptor;
static {
descriptor = new HashMap<>();
descriptor.put("id", MyClass::getId);
descriptor.put("name", MyClass::getName);
}
private String id;
private String name;
public String getId() {
return id;
}
public String getName() {
return name;
}
public void setId(String value) {
id = value;
}
public void setName(String value) {
name = value;
}
public Object getFieldValue(String fieldName) {
Function fn = descriptor.get(fieldName);
return fn.apply(this);
}
}
public static void main(String []args){
MyClass mc = new MyClass();
mc.setId("hello");
mc.setName("world");
System.out.println(mc.getFieldValue("id") + " " + mc.getFieldValue("name"));
}
}
To note that in the above example the cyclomatic complexity is somewhat still there, but it's moved in the class' static initialiser. This means that you'll suffer a modest penalty during application startup but enjoy higher performance in subsequent calls of getFieldValue.
Also, if performance is what you're after you may want to eliminate the need for toLowerCase... which in my example I removed.
Instead of the switch or using a Map, you can use an enum.
enum FieldExtractor implements Function<YourClass, String> {
ID(YourClass::getId),
NAME(YourClass::getName); // and so on
private final Function<YourClass, String> delegate;
FieldExtractor(Function<YourClass, String> delegate) {
this.delegate = delegate;
}
#Override public String apply(YourClass extractFrom) {
return delegate.apply(extractFrom);
}
static FieldExtractor fromString(String name) {
return Stream.of(FieldExtractor.values())
.filter(fe -> fe.name().equalsIgnoreCase(name))
.findFirst()
.orElseThrow(IllegalArgumentException::new);
}
}
Now you can use
public String getFieldValue(String fieldName) {
return FieldExtractor.fromString(fieldName).apply(this);
}
in your client code.
I'm using a few components that I cannot edit, my situation is like this
private enum Radio {
SPACE(" "),
PLUS("+"),
MINUS("-");
private String value;
private Radio(final String value) {
this.value = value;
}
public static void setSelection(final CodeEntry entry, final String flag) {
entry.getButtonWhite().setSelection(flag.equals(SPACE.value));
entry.getButtonGreen().setSelection(flag.equals(PLUS.value));
entry.getButtonRed().setSelection(flag.equals(MINUS.value));
}
}
I don't like this. I want to associate the button with the enum. Anything else is sub-par to say the least. But I don't know how
private enum Radio {
SPACE(" ", CodeEntry::getButtonWhite),
PLUS("+", CodeEntry::getButtonGreen),
MINUS("-", CodeEntry::getButtonRed);
...
static reference to the non-static method getButtonWhite()
What I want is a sort of accept(T t) thing. So I give a getter as a constructor parameter, then I call that getter on an object with enum.accept(t), like so:
private enum Radio {
SPACE(" ", CodeEntry::getButtonWhite),
PLUS("+", CodeEntry::getButtonGreen),
MINUS("-", CodeEntry::getButtonRed);
setSelection(final CodeEntry entry, final String flag) {
// Button button = Radio.valueOf(flag).accept(entry);
// button.setSelection(true);
Radio.valueOf(flag).accept(entry).setSelection(true);
}
I'm not sure if this is possible, and the syntax is kinda defeating me.
Limitations of my example
While I appreciate any workable answer, the following things I cannot change so I'll only accept an answer that ticks the following:
The flag is string and will be a string no matter what.
The entries will have getButtonX, that will not change.
I am using java 8, that will not change.
I want to associate the getter with the enum, it must be a constructor param.
Because you haven't specified the type(s) that the CodeEntry::getButton* methods return, I'm going to denote it T for my example.
Your second enum parameter can be a Function<CodeEntry, T>, which will allow you to use a method reference:
private enum Radio {
SPACE(" ", CodeEntry::getButtonWhite),
PLUS("+", CodeEntry::getButtonGreen),
MINUS("-", CodeEntry::getButtonRed);
private final String value;
private final Function<CodeEntry, T> buttonFunction;
private Radio(final String value, Function<CodeEntry, T> buttonFunction) {
this.value = value;
this.buttonFunction = buttonFunction;
}
public static void setSelection(final CodeEntry entry, final String flag) {
Arrays.stream(values())
.filter(radio -> flag.equals(radio.value))
.findAny()
.ifPresent(radio -> {
radio.buttonFunction.apply(entry).setSelection(true);
});
}
}
This assumes that the flag parameter will be either " ", "+", or "-".
Here is a solution using an abstract method:
private enum Radio {
SPACE(" ") {
#Override
public void setSelection(final CodeEntry entry, final String flag) {
// do whatever
}
},
...
public abstract void setSelection(final CodeEntry entry, final String flag);
Honestly I had a little trouble understanding exactly what you wanted, but hopefully that helps?
I'm writing a library, which has a predefined set of values for an enum.
Let say, my enum looks as below.
public enum EnumClass {
FIRST("first"),
SECOND("second"),
THIRD("third");
private String httpMethodType;
}
Now the client, who is using this library may need to add few more values. Let say, the client needs to add CUSTOM_FIRST and CUSTOM_SECOND. This is not overwriting any existing values, but makes the enum having 5 values.
After this, I should be able to use something like <? extends EnumClass> to have 5 constant possibilities.
What would be the best approach to achieve this?
You cannot have an enum extend another enum, and you cannot "add" values to an existing enum through inheritance.
However, enums can implement interfaces.
What I would do is have the original enum implement a marker interface (i.e. no method declarations), then your client could create their own enum implementing the same interface.
Then your enum values would be referred to by their common interface.
In order to strenghten the requirements, you could have your interface declare relevant methods, e.g. in your case, something in the lines of public String getHTTPMethodType();.
That would force implementing enums to provide an implementation for that method.
This setting coupled with adequate API documentation should help adding functionality in a relatively controlled way.
Self-contained example (don't mind the lazy names here)
package test;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<HTTPMethodConvertible> blah = new ArrayList<>();
blah.add(LibraryEnum.FIRST);
blah.add(ClientEnum.BLABLABLA);
for (HTTPMethodConvertible element: blah) {
System.out.println(element.getHTTPMethodType());
}
}
static interface HTTPMethodConvertible {
public String getHTTPMethodType();
}
static enum LibraryEnum implements HTTPMethodConvertible {
FIRST("first"),
SECOND("second"),
THIRD("third");
String httpMethodType;
LibraryEnum(String s) {
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
static enum ClientEnum implements HTTPMethodConvertible {
FOO("GET"),BAR("PUT"),BLAH("OPTIONS"),MEH("DELETE"),BLABLABLA("POST");
String httpMethodType;
ClientEnum(String s){
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
}
Output
first
POST
Enums are not extensible. To solve your problem simply
turn the enum in a class
create constants for the predefined types
if you want a replacement for Enum.valueOf: track all instances of the class in a static map
For example:
public class MyType {
private static final HashMap<String,MyType> map = new HashMap<>();
private String name;
private String httpMethodType;
// replacement for Enum.valueOf
public static MyType valueOf(String name) {
return map.get(name);
}
public MyType(String name, String httpMethodType) {
this.name = name;
this.httpMethodType = httpMethodType;
map.put(name, this);
}
// accessors
public String name() { return name; }
public String httpMethodType() { return httpMethodType; }
// predefined constants
public static final MyType FIRST = new MyType("FIRST", "first");
public static final MyType SECOND = new MyType("SECOND", "second");
...
}
Think about Enum like a final class with static final instances of itself. Of course you cannot extend final class, but you can use non-final class with static final instances in your library. You can see example of this kind of definition in JDK. Class java.util.logging.Level can be extended with class containing additional set of logging levels.
If you accept this way of implementation, your library code example can be like:
public class EnumClass {
public static final EnumClass FIRST = new EnumClass("first");
public static final EnumClass SECOND = new EnumClass("second");
public static final EnumClass THIRD = new EnumClass("third");
private String httpMethodType;
protected EnumClass(String name){
this.httpMethodType = name;
}
}
Client application can extend list of static members with inheritance:
public final class ClientEnum extends EnumClass{
public static final ClientEnum CUSTOM_FIRST = new ClientEnum("custom_first");
public static final ClientEnum CUSTOM_SECOND = new ClientEnum("custom_second");
private ClientEnum(String name){
super(name);
}
}
I think that this solution is close to what you have asked, because all static instances are visible from client class, and all of them will satisfy your generic wildcard.
We Fixed enum inheritance issue this way, hope it helps
Our App has few classes and each has few child views(nested views), in order to be able to navigate between childViews and save the currentChildview we saved them as enum inside each Class.
but we had to copy paste, some common functionality like next, previous and etc inside each enum.
To avoid that we needed a BaseEnum, we used interface as our base enum:
public interface IBaseEnum {
IBaseEnum[] getList();
int getIndex();
class Utils{
public IBaseEnum next(IBaseEnum enumItem, boolean isCycling){
int index = enumItem.getIndex();
IBaseEnum[] list = enumItem.getList();
if (index + 1 < list.length) {
return list[index + 1];
} else if(isCycling)
return list[0];
else
return null;
}
public IBaseEnum previous(IBaseEnum enumItem, boolean isCycling) {
int index = enumItem.getIndex();
IBaseEnum[] list = enumItem.getList();
IBaseEnum previous;
if (index - 1 >= 0) {
previous = list[index - 1];
}
else {
if (isCycling)
previous = list[list.length - 1];
else
previous = null;
}
return previous;
}
}
}
and this is how we used it
enum ColorEnum implements IBaseEnum {
RED,
YELLOW,
BLUE;
#Override
public IBaseEnum[] getList() {
return values();
}
#Override
public int getIndex() {
return ordinal();
}
public ColorEnum getNext(){
return (ColorEnum) new Utils().next(this,false);
}
public ColorEnum getPrevious(){
return (ColorEnum) new Utils().previous(this,false);
}
}
you could add getNext /getPrevious to the interface too
#wero's answer is very good but has some problems:
the new MyType("FIRST", "first"); will be called before map = new HashMap<>();. in other words, the map will be null when map.add() is called. unfortunately, the occurring error will be NoClassDefFound and it doesn't help to find the problem. check this:
public class Subject {
// predefined constants
public static final Subject FIRST;
public static final Subject SECOND;
private static final HashMap<String, Subject> map;
static {
map = new HashMap<>();
FIRST = new Subject("FIRST");
SECOND = new Subject("SECOND");
}
private final String name;
public Subject(String name) {
this.name = name;
map.put(name, this);
}
// replacement for Enum.valueOf
public static Subject valueOf(String name) {
return map.get(name);
}
// accessors
public String name() {
return name;
}
In preparing for an interview, someone mentioned knowing how to make a class/method in java read-only. I've been doing a bit of searching, but haven't found anything really concrete.
Maybe this question is simpler to answer than I'm making it out to be, but what would be a way to make a class or method read-only in java?
The following code will ensure that your class is always READ ONLY, but if you find any loop hole, please post it here.
import java.io.Serializable;
final public class ImmutableClass implements Cloneable,Serializable {
private static final long serialVersionUID = 6488148163144293060L;
private static volatile ImmutableClass instance;
private ImmutableClass() {
// no-op
System.out.println("instance created : " + this.hashCode());
}
/**
* Lazy Instantiation
*
* #return
*/
public static ImmutableClass getInstance() {
if (instance == null) {
synchronized (ImmutableClass.class) {
System.out.println("aquired lock");
if (instance == null) {
instance = new ImmutableClass() {
};
}
System.out.println("released lock");
}
}
return instance;
}
public Object readResolve() {
System.out.println("readResolve()");
return getInstance();
}
#Override
public Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
}
The Read-only class means, we are talking about "IMMUTABLE" concept.
The following example depicts the same:
public class ImmutableString {
static String upcase(String s) {
return s.toUpperCase(); // here local variable s vanishes
// it return the value to a new String object
}
public static void main(String[] args) {
String s = new String("abc");
System.out.println(s); //abc
String s1 = upcase(s);
System.out.println(s1); //ABC
System.out.println(s); //abc
}
}
Lets Say you want a read only version of an object,
case 1: if your class contains fields which are not pointers to any other objects eg:
public class Person{
private String name;
//Getters n Setters
}
in this case, you can return a copy of this class, write a constructor that accepts Person, any one who wants to get a Person object will have a copy of this object so any Setter operations wont effect the original object(Strings are immutable)
Case 2: in case your object contains a pointer to another object or list or map
in this case make classes implement an interface which has only read-only methods(Getters) and wherever you are returning the object, change it to return this interface, so client will have access to only read-only methods
eg:
class Person implements ReadOnly{
String name;
.. assume pointers also in here
// Getter n Setters
public PersonReadOnly(){
return this;
}
}
interface PersonReadOnly {
public String getName();
}
Simple rule: Don't have any public fields and No public setter methods.
For example, see class below:
final class AReadOnlyClass
{
private int anInt;
public int GetAnInt()
{
return anInt;
}
}