I am using java 6 and my application is huge and its developed in java 6.
Now we trying to upgrade java version as 7.
But when i tried it to java 7 it will give compilation error in enum class.
In enum class i have defined valueOf() method so in java 7 it gives compilation error .
Code
public enum TestEnum {
TESTONE,TESTTWO, NONE;
public String toString() {
switch(this) {
case TESTONE:
return "Test one";
case TESTTWO:
return "Test two";
case NONE:
return "None";
}
return null;
};
public static TestEnum valueOf(Class<TestEnum> enumType, String value){
if(value.equalsIgnoreCase(TESTONE.toString()))
return TestEnum.TESTONE;
else if(value.equalsIgnoreCase(TESTTWO.toString()))
return TestEnum.TESTTWO;
else if(value.equalsIgnoreCase(NONE.toString()))
return TestEnum.NONE;
else
return null;
}
}
Error
Name clash: The method valueOf(Class<TestEnum>, String) of type TestEnum has the
same erasure as valueOf(Class<T>, String) of type Enum<E> but does not hide it TestEnum.java
Update(Resolved)
I changes valueOf() method and my file is compile.
public static TestEnum valueOf(TestEnum enumType, String value){
if(value.equalsIgnoreCase(TESTONE.toString()))
return TestEnum.TESTONE;
else if(value.equalsIgnoreCase(TESTTWO.toString()))
return TestEnum.TESTTWO;
else if(value.equalsIgnoreCase(NONE.toString()))
return TestEnum.NONE;
else
return null;
}
I'm not sure why it was working in Java 6, as [a method with that signature previously existed in Java 6](https://docs.oracle.com/javase/6/docs/api/java/lang/Enum.html#valueOf(java.lang.Class, java.lang.String)) (and has since Java 5).
However, for the sake of your developers' sanity, I would strongly recommend that you rename the method anyway: Enum.valueOf does something well-known, and you are attempting to provide a method which does something different. This would violate the principle of least surprise, and likely lead to unintentional results.
A name like TestEnum.forName(String) is a possible alternative.
Additionally: a switch in an enum over a variable of the type of that enum is a bit of a code smell. You can express the enum more nicely:
enum TestEnum {
TESTONE("Test one"),TESTTWO("Test two"), NONE("None");
private String str;
private TestEnum(String str) {
this.str = str;
}
#Override public String toString() {
return str;
}
}
which has the additional advantage of you not being able to accidentally omit the "string" form of any further enum values you add.
Similarly, you can do better than explicitly testing the string values:
enum TestEnum {
/* values */;
private static HashMap<String, TestEnum> forNameMapping;
{
forNameMapping = new HashMap<>();
for (TestEnum t : TestEnum.values()) {
forNameMapping.put(t.str.toLowerCase(), t);
}
}
public static TestEnum forName(String str) {
return forNameMapping.get(str.toLowerCase());
}
}
Every enum is a subclass of Enum<T>. Enum<T> already defines a static method with the erasure valueOf(Class,String). Since static methods cannot be overridden, you cannot define a static method with the same signature. You will have to call your method differently.
Related
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.
I'm facing a problem with nested enum. So, I have an nested enum which has default values as you can see. Before there were just an enums like CDs and CMs. Now I set something like definition to every of it as you can see "Cool Ds" and etc. Currently I'm facing a problem that I can't read enums String, which is in () and I don't know how to fix it anymore. Does anyone have an idea?
package com.test.beans;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
#JsonIgnoreProperties(ignoreUnknown = true)
public class RecordBean implements Serializable {
public enum Types {
CDs("Cool Ds"), CMs("Cool Ms");
private final String s;
private Types(String s) {
this.s=s;
}
public String getTypes(){
return s;
}
public static Types fromNumeric(int index) {
switch (index) {
default:
return null;
case 0:
return Types.CDs;
case 1:
return Types.CMs;
}
}
}
private Types type;
private float value;
public RecordBean() {
// default constructor for default instantiate
}
public RecordBean(Types type, float value) {
this.type = type;
this.value = value;
}
public Types getType() {
return type;
}
public void setType(Types type) {
this.type = type;
}
public float getValue() {
return value;
}
public void setValue(float value) {
this.value = value;
}
}
UPDATE
Error what I'm getting:
17/04/10 12:44:53 ERROR App$: Can not construct instance of com.test.beans.RecordBean$Types from String value 'Cool Ds': value not one of declared Enum instance names: CDs, CMs ]
So as you can see he is not comparing my String 'Cool Ds' with enums String in brackets but with pure enum or CDs and CMs
My USE-CASE is like this. I'm working spark streaming where data are incoming to my RecordBean class and where are comparing to my enum type. Because in database are changed types from CMs to Cool Ms I needed to change the same in my app by adding definition to Enum. Afterwards I couldn't accomplish part where app will process enum like CMs and read its definition or Cool Ms
Be sure, you can read with : CDs.getTypes() and CMs.getTypes()
Guessing: maybe the framework is calling toString() on your enum constants, thus you might want to add:
public enum Types {
...
#Overrride
public String toString() { return s; }
In other words: make sure that your existing enum constants are really using that "new" changed string name.
But beyond that: consider stepping back and changing your overall design. Your problem isn't uncommon - enums are nice from a programming point of view (as in: using enum constants leads to cleaner code); but: they are not suited for persistence. Versioning with enums is hell.
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
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))
I need to re-implement the enum.valueof method of a few of my enumerations so they no longer throw exceptions, instead they simply return null if a value doesn't exist in the enumeration.
I'm trying the basic
#Override
public static <T extends Enum<T>> T valueOf(Class<T> enumType,
String name){
but it's not working, saying I need to override or implement a super type.
I can come up with a super class I guess, but I'm just not sure how to put this together. Any ideas?
You can't. You'll have to define another, different method. The valueOf method is automatically generated by the compiler.
public static MyEnum permissiveValueOf(String name) {
for (MyEnum e : values()) {
if (e.name().equals(name)) {
return e;
}
}
return null;
}
Use Apache Commons Lang:
MyEnum myEnum = EnumUtils.getEnum(MyEnum.class, "MY_ENUM_VALUE");
Quote from the Javadoc for EnumUtils.getEnum:
Gets the enum for the class, returning null if not found.
This method differs from Enum.valueOf(java.lang.Class,
java.lang.String) in that it does not throw an exception for an
invalid enum name.
Is it absolutely necessary that the method is called valueOf like the method that enums have automatically? In the project that I'm currently working on we have similar methods, but we call them differently; for example, forName:
public static ESomeEnum forName(String name) {
for (ESomeEnum e : ESomeEnum.values()) {
if (e.name().equals(name)) {
return e;
}
}
return null;
}
You don't have to override valueOf. Here's what I did:
I had to "parse" some strings to enums and they didn't match with their declaration names, so I did a sort of reimplementation of valueOf(String name).
public enum Command {
DIR("DIR"),
PUT("PUT"),
GET("GET"),
OK("OK"),
ERROR("ERROR"),
READY("READY"),
FIN("#FIN#");
private String name;
private Command(final String name) {
this.name = name;
}
/**
* Returns the desired Enum or throws an exception
* #param commandName - String with the name contained by the Enum that you want
* #return Command
*/
public static Command getEnum(String commandName){
// if the string is "#FIN#" returns Command.FIN.
if(FIN.toString().equals(commandName)){
return FIN;
}
// if the name matches any of the remaining enums return whichever one matches
else if(Arrays.asList(Command.values()).contains(Command.valueOf(commandName))){
return Command.valueOf(commandName);
}
// if it still wasn't found, throw an exception
throw new IllegalArgumentException("No enum defined for this string: " + commandName);
}
#Override
public String toString(){
return name;
}
}
This code is tested and works.
You can use like:
Command k = Command.getEnum("#FIN#");
System.out.println(k.name() + " " +k.toString());
k = Command.getEnum("PUT");
System.out.println(k.name() + " " +k.toString());
And it's output would be:
FIN #FIN#
PUT PUT
Hope it helps.
You might consider creating a new (different name such as convert) static method in your enum classes.
public enum MyEnum{
....
public static MyEnum convert(Object value){
...
}
}