Enumeration value not returning with valueOf - java

I am confused at what is going on here. It's a simple thing but for some reason I am getting the name of the enumeration and not the value.
Here is my class :
public class Class1{
public enum SchoolEnum {
01("MIDDLE_SCHOOL");
private String value;
SchoolEnum(String value) {
this.value = value;
}
#Override
public String toString() {
return String.valueOf(value);
}
}
private SchoolEnum schoolEnum = null;
public SchoolEnum getSchoolEnum () {
return schoolEnum;
}
public void setSchoolEnum (SchoolEnum schoolEnum ) {
this.schoolEnum= schoolEnum;
}
}
Calling it in another class via this :
Class1 response = new Class1();
response.setSchoolEnum(Class1.SchoolEnum.valueOf("01"));
Whenever I try to get the value of the 01 Enum, I am simply getting 01 instead of the value MIDDLE_SCHOOL. What is going on here ?

I think your declaration is wrong.
01("MIDDLE_SCHOOL");
Above declaration will give you compile time error. As any variable name can't start with digit.
Some naming suggestions you can use.
_01("MIDDLE_SCHOOL");
ONE("MIDDLE_SCHOOL");
ZERO_ONE("MIDDLE_SCHOOL");

Related

Java - how to call a method of corresponding class based on string using enum/factory pattern

Yes, I read many examples in web, but I didn't find a way how to call a method based on string value. May be I am not searching in right way... I wrote all code, but don't know how to call the method.
fyi: I don't want to use if else or switch case
Here is what I want:
I get the card reader type as String from database. I have to call the corresponding class' method.
My code:
LoginPanel.java
public class LoginPanel {
public static void main(String args[]) {
String readerType = "Omnikey5427-CK"; // I get this ("Omnikey5427-CK" or "Omnikey5427-G2") from a database as String
// I WANT TO CALL getCardNumber() method of respective class
}
}
ISmartCardReader.java
public interface ISmartCardReader {
public Integer getCardNumber();
}
Omnikey5427G2.java
public class Omnikey5427G2 implements ISmartCardReader {
public Omnikey5427G2() {
System.out.println("G222222222222222...");
}
public Integer getCardNumber() {
return 222;
}
}
Omnikey5427CK.java
public class Omnikey5427CK implements ISmartCardReader {
public Omnikey5427CK() {
System.out.println("CKKKKKKKKKKKKKKK...");
}
public Integer getCardNumber() {
return 111;
}
}
SmacrtCardEnumFactory.java
public enum SmacrtCardEnumFactory {
OMNIKEY5427CK("Omnikey5427-CK") {
public ISmartCardReader geInstance() {
return new Omnikey5427CK();
}
},
OMNIKEY5427G2("Omnikey5427-G2") {
public ISmartCardReader geInstance() {
return new Omnikey5427G2();
}
};
private String cardReaderName;
private SmacrtCardEnumFactory(String cardReaderName) {
this.cardReaderName = cardReaderName;
}
public String cardReaderName() {
return cardReaderName;
}
}
You can use valueOf() function of enum provided your enum sonstant names match strings used to lookup (you may use cardName.toUpper()). You may also create objects for all the card types and store them in a hash map and then lookup them. You can also write some fatory method, but this will be if-then-else or switch inside
You could iterate over the factory's values() and get the one that matches the string:
public enum SmacrtCardEnumFactory {
// current code omitted for brevity
public static getSmartCardReader(String name) {
return Arrays.stream(values())
.filter(r -> r.cardReaderName().equals(name))
.map(SmacrtCardEnumFactory::getInstance();
.orElse(null);
}
}

Implementing same behavior between Enums : this static method cannot hide the instance method from interface

I have a common process with different progress values and step number, depending on the user.
To solve this I've made an interface :
public interface Progress {
int getTotalStepNumber();
int getIndex();
String getMessage();
#Override
String toString();
}
So a step process implementation is like this, litteraly, it is an enumeration of the steps for this process :
public enum ProgressImplementationOfProcessOne implements Progress {
STEP_ONE(1, "Step one message."),
STEP_TWO(2, "Step two message.");
// ... etc. with more steps
/**
* Number of steps for this process.
*/
private static final int STEPS = 2;
private int index;
private String message;
ProgressImplementationOfProcessOne(int index, String message) {
this.index = index;
this.message = message;
}
#Override
public int getTotalStepNumber() { return STEPS; }
#Override
public int getIndex() { return this.index; }
#Override
public String getMessage() { return this.message; }
#Override
public String toString() { return this.message; }
}
But then I thought it would be nice to find the corresponding step from implementation as well, with the method valueOf() of enumerations. So I added the following lines to my interface :
default Progress valueOf(String s) {
for (Progress progress : this.getValues()) {
if (progress.getMessage().equals(s)) {
return progress
}
}
return null;
}
default Progress valueOf(int i) {
for (Progress progress : this.getValues()) {
if (progress.getIndex() == this.getIndex()) {
return progress;
}
}
return null;
}
Since there is no getValues() method in the interface Progress I added the following method to it (thinking "the enum implementation will handle it natively").
default List<Progress> getValues() { return null; }
But I don't understand why I get this error for each ProgressImplementation :
This static method cannot hide the instance method from Progress..
I know I could do it by creating an additional class ProgressStep which replace an enum value, and replace enum by classes with attributes and so on, but since enum can handle multiple values I thought it could have been easier with it.
Simply rename the valueOf to something like valueOfEnum, as valueOf is already specified by java.lang.Enum.
public static <T extends Enum<T>> T valueOf(Class<T> enumType,
String name) {
T result = enumType.enumConstantDirectory().get(name);
if (result != null)
return result;
if (name == null)
throw new NullPointerException("Name is null");
throw new IllegalArgumentException(
"No enum constant " + enumType.getCanonicalName() + "." + name);
}
The comment on that method contains following section:
Note that for a particular enum type T, the implicitly declared public static T valueOf(String) method on that enum may be used instead of this method to mapfrom a name to the corresponding enum constant. All theconstants of an enum type can be obtained by calling the implicit public static T[] values() method of that type
Emphasis mine
As you can see, valueOf(String s) is already declared on every enum class which in turn is the reason, you can't have it in an interface on any enum

Tuple Enum in Java

I'm very new in Java and were wondering and didn't find anything about it.
Can you create enum tuple ?
public enum Status {OPEN : "1", CLOSED: "2", DELETED: "3"}
I will need to access both "OPEN" or "1"
You could always create a custom constructor for your enum..
public enum Status {
OPEN("1"),
CLOSED("2"),
DELETED("3");
private String code;
public Status(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}
Then you can access with Status.OPEN.getCode(). This functions as an effective mapping between an enum type and a code value.
You can do something like this:-
public enum Currency {PENNY(1), NICKLE(5), DIME(10), QUARTER(25)};
But for this to work you need to define a member variable and a constructor because PENNY (1) is actually calling a constructor which accepts int value , see below example.
public enum Currency {
PENNY(1), NICKLE(5), DIME(10), QUARTER(25);
private int value;
private Currency(int value) {
this.value = value;
}
};
Constructor of enum in java must be private any other access modifier will result in compilation error. Now to get the value associated with each coin you can define a public getValue() method inside java enum like any normal java class. Also semi colon in the first line is optional.
private int getValue() { return value; }
and get values like this:-
PENNY.getValue(); //returns int 1
Refrence:
Solution by #christopher cover only first part. Creating ENUM.
You will need one more method that match code with enum value:
public static Status byCode(String code){
for(Status s : Status.values()) {
if (s.code.equals(code)) {
return s;
}
}
throw new IllegalArgumentException("Code does not match");
}
now you can get enum value by name and by code.

Java impose final programmatically

What's the proper way to ensure a value only gets set once, although the time it will be set is unknown (ie: not in the constructor). I could do a null check or keep track of a flag and throw an exception - but what exception should I throw? It's for a small, localized library and I prefer not to create my own ValueAlreadyAssigned exception for such a seemingly generic case.
In the setter. Do it like this:
private foo bar;
public void setFoo(foo bar) {
if (this.bar == null) {
this.bar = bar;
} else {
System.out.println("Don't touch me!");
// J/K Throw an IllegalStateException as Michal Borek said in his answer.
}
}
The method could throw IllegalStateException, since it's javadocs say:
Signals that a method has been invoked at an illegal inappropriate
time.
IMHO definition of your own exception is not a big deal especially if it extends RuntimeException. So I'd suggest you to define ValueAlreadySetException extends IllegalStateException and use it.
The next point is the logic into each setter you have to duplicate according to #Renan's suggestion. I'd suggest you the following. Define special generic container and use it:
public class SetOnceContainer<T> {
private Class<T> type;
private String name;
private T value;
private boolean set = false;
public SetOnceContainer(Class<T> type, String name) {
this.type = type;
this.name = name;
}
public void set(T value) {
if (set) {
throw new ValueAlreadySetException(name);
}
this.value = value;
this.set = true;
}
public T get() {
return value;
}
}
Please pay attention that this implementation supports null values too.
Now you can use it as following:
public MyClass {
private SetOnceContainer<Integer> number = new SetOnceContainer<Integer>(Integer.class, "number");
private SetOnceContainer<String> text = new SetOnceContainer<String>(String.class, "text");
public void setNumber(int value) {
number.set(value);
}
public void setText(String value) {
text.set(value);
}
public Integer getNumber() {
return number.get();
}
public String getText() {
text.get();
}
}
The implementation is encapsulated into once point. You can change it in once place if you need. Null values are supported too. The setters and getters are just a little bit more complicated than regular.

java - an enum question

I have encountered a weird problem in my app (java).
I have an enum. Something like that
public enum myEnum implement myIntrface{
valueA(1),valueb(2),valuec(3),valued(4)
private int i;
// and then - a constructor
public MyEnum(int number){
i = number;
}
private MyObj obj = new MyObj;
// getter and setter for obj
}
and in another class I have this
MyEnum.valueA.setObj(new Obj(...))
in briefe - I have an enum with a private instance member that has a set and a get.
So far so good -
The only thing that amazes me is that later on I look at the value of the MyEnum.valueA().obj is null.
there is nothing that updates the value to null, I have even gave it a default value in the constructor and I still see it null later.
any suggestions?
Enums should be un-modifiable classes so you shouldn't really be doing this. If your looking to modify the state of a type based object like an enum you should use an final class approach with embedded constants. Below is an example of a class based approach with a modifiable name an a un-modifiable name...
public final class Connection {
public static final Connection EMAIL = new Connection("email");
public static final Connection PHONE = new Connection("phone");
public static final Connection FAX = new Connection("fax");
/**/
private final String unmodifiableName; //<-- it's final
private String modifiableName;
/*
* The constructor is private so no new connections can be created outside.
*/
private Connection(String name) {
this.unmodifiableName = name;
}
public String getUnmodifiableName() {
return unmodifiableName;
}
public String getModifiableName() {
return modifiableName;
}
public void setModifiableName(String modifiableName) {
this.modifiableName = modifiableName;
}
}
The purpose of enums is to represent constant values. It does not make any sense to set the fields of a constant value.
You should declare your fields as final, and use the constructor to initialize all of them.
For reference, the following code works as expected:
public class Test {
public static enum MyEnum {
valueA(1),valueb(2),valuec(3),valued(4);
private int i;
private Object o;
private MyEnum(int number) {
i = number;
}
public void set(Object o) {
this.o = o;
}
public Object get() {
return o;
}
}
public static void main(String[] args) {
System.out.println(MyEnum.valueA.get()); // prints "null"
MyEnum.valueA.set(new Integer(42));
System.out.println(MyEnum.valueA.get()); // prints "42"
}
}
the cause of this problem is the db40 framework . It loads an enum from the db using reflection. This is well documented .
http://developer.db4o.com/Forums/tabid/98/aft/5439/Default.aspx

Categories