I am trying to use guava's getIfPresent() for an enum as below:
private enum LegalColumns
{
PRODUCERS_CUT("PRODUCER'S CUT", PMCColumnsEnum.NETWORK_CUT_1.getColumnName()),
PROPOSED_LOCKED_CUT("PROPOSED LOCKED CUT", PMCColumnsEnum.NETWORK_CUT_3.getColumnName()),
LOCK("LOCK", PMCColumnsEnum.LOCKED_DELIVERY.getColumnName()),
FINAL_MIX("FINAL MIX", PMCColumnsEnum.MIX_DATE.getColumnName());
private String column;
private String replacementColumn;
LegalColumns(String column, String replacementColumn) {
this.column = column;
this.replacementColumn = replacementColumn;
}
public static LegalColumns getIfPresent(String column) {
System.out.println(Enums.getIfPresent(LegalColumns.class, column.trim().toUpperCase()));
return Enums.getIfPresent(LegalColumns.class, column.toUpperCase()).orNull();
}
}
When I step through this however, it always prints out Optional.absent() despite the strings being exact matches. I followed, to my knowledge, the guava spec exactly. Any ideas what I am missing?
https://google.github.io/guava/releases/15.0/api/docs/com/google/common/base/Enums.html#getIfPresent(java.lang.Class,%20java.lang.String)
Returns an optional enum constant for the given type, using
Enum.valueOf(java.lang.Class, java.lang.String). If the constant
does not exist, Optional.absent() is returned. A common use case is
for parsing user input or falling back to a default enum constant. For
example, Enums.getIfPresent(Country.class,
countryInput).or(Country.DEFAULT);
https://docs.oracle.com/javase/6/docs/api/java/lang/Enum.html?is-external=true#valueOf(java.lang.Class,%20java.lang.String)
Returns the enum constant of the specified enum type with the
specified name. The name must match exactly an identifier used to
declare an enum constant in this type. (Extraneous whitespace
characters are not permitted.)
From your comment
I have gone with another approach, but for others, I passed in columns like "FINAL MIX".
"FINAL MIX" != "FINAL_MIX"
Guava uses the enum identifier, not the string you pass into the constructor.
So for the enum instance, FINAL_MIX("FINAL MIX", PMCColumnsEnum.MIX_DATE.getColumnName()); the enum identifier is "FINAL_MIX" not the string you pass in "FINAL MIX"
IN ADDITION! as you do not define a Locale on your string.toUpperCase, you are at risk of the turkey I bug.
Related
I have the callback set up correctly in btrace. My argument list contains a custom Enum object. I want to print something if the Enum object equals to a specific value. I am OK with either comparing the Enum object directly, or comparing the string representation of that Enum object with a constant string.
However, the str() function doesn't return me the string representation of this Enum object. It returs the path$class#hash.
How can I compare Enum object in btrace?
Thanks!
Erben
Found the answer. The string representation of an Enum is stored in the "name" field of this Enum object. So use reflection to get the value of that "name" field from the object like this:
private static Field enumNameField = field("java.lang.Enum", "name");
String stringRepresentation = (String) get(enumNameField, enumObject);
I'm sure this question has allready been answered somewhere, but I' ve searched for half an hour now and I'm running out of keywords, because I have absolutly no idea how to do this.
I have a constructor for a class like this
public MyClass (String name)
{}
what I want is to define Strings so that only those Strings can be entered.
I assume it has something to do with static final strings, but there is quite a lot to be found to those and I dont know how to narrow down the search. Please tell me how that thing I want to do is called, so that I can search for it.
Edit:
Example to what I want:
I want to somehow define a number of Strings. (Or do somethig else that has the same effect, as I said I dont know how to do it)
String one = "ExampleOne";
String two = "ExampleTwo";
so that when I call the constuctor
MyClass myClass = new MyClass("somethingElse");
the constructor wont take it. Or even better eclipse allready showing my what options I have like it does whit "Color. "
Yes you have right you can not override String class because it is final so simply you can create your own StringWrapper class that wraps string.
public class StringWrapper{
private String content;
public StringWrapper(String c){
content = c;
}
//all your methods and fields there, for example delegated methods
public String toString(){
return content.toString();
}
}
But Enum could be also used in your case then you define your Enum values
public enum Color {
WHITE, BLACK, RED, YELLOW, BLUE; //; is required here.
#Override public String toString() {
//only capitalize the first letter
String s = super.toString();
return s.substring(0, 1) + s.substring(1).toLowerCase();
}
}
public myClass (Color color)
{}
There are two ways you can acheive this, either use a enum as constructor parameter. The enum itself contains only the allowed values, which is what I would do, keep everythign nice an oop and you can add logic to enums at a later date.
Or alternatively you can just check if the constuctor paramters value is valid, by performing a comparison and throwing an exception if not in allowed values. Have a predfined list and then, myList.contains(myString) - throw exception if false.
What I want is to define String so that only those Strings can be entered
I think that what you are after are Enums.
Enums will allow you to define a range of values which you can then use. In the example I have linked, the developer can restrict the type of input that he/she will receive to the days of the week.
You can check it in constructor's body at runtime, or if you want to compile-time checks, then you can use enum type argument (enum is a predefined set of constants).
From what I understand it seems like you want to limit what the String can be.
You would do this by putting conditional statements inside the constructor to weed out any Strings you don't want to be entered that would either notify the user that it is an invalid string or throw an exception, and the remainder of the constructor would only be executed in an else statement once it has passed all the tests making sure it is a valid String
I have 3 ints named A, B, and C. These are to be multiplied with the number 52. I have a string that contains the name of which int I want to mulitply (in example below my string type == A;.
I want to know if there is anyway to make the name of the String change into the name of the object/int that I wish to use.
What I have right now:
public class MultiplySomeNumbers{
int A = 100;
int B = 200;
int C = 300;
String type = "A";
final int multiplied = 52;
public int multiply(String type){
return multiplied* ____ //What goes here?
}
}
I DON'T want to do anything like this:
public int multiply(String type){
if(type.equalsIgnoreCase("A"){
return multiplied*A;
}else if(type.equalsIgnoreCase("B"){
...
Any help would be greatly appreciated!
No, that is not possible (maybe with Reflection, but it's still a no-go). Every single situation where you think you might need this does not need it.
There are several issues, but here are a few:
No intellisense for those generated variables
Very unclear code
Ambiguous naming (what if you create a new variable that happens to have the same name as a generated one?)
etc etc etc
You will have to go with your second option.
We might be able to provide a different solution, but the question is rather unclear as it is right now. Perhaps you could expand a little so we can help you better.
Although there may be a way to do this with reflection, it's probably a really bad idea. If you really can't just pass in the value, but want to specify a limited set of constants by which you can multiply, I'd recommend creating an enumerated type.
Taking your same example, but using an enum instead of trying to look up constants by name, would look something like this:
public class MultiplySomeNumbers{
public enum Type {
A(100),
B(200),
C(300);
private final int value;
private Type(int value) {
this.value = value;
}
public final int getValue() {
return value;
}
}
Type type = Type.A;
final int multiplied = 52;
public int multiply(Type type){
return multiplied * type.getValue();
}
}
While there is nothing wrong with using an enum for this solution, it may not be the most flexible solution. Enums are, by design, effectively immutable ... they are intended to have the sense of constants. If you wish to change the value of a variable by multiplying its value by 52, then this is not possible with enums.
What I think you really should do is use a HashMap. A Map is a key / value pair.
The key is the "variable's name"; a String quantity
The value is the "variable's current value"; an Integer quantity (not int!)
Your Map can be declared like this:
Map<String, Integer> myVariables = new HashMap<String, Integer>();
then to load your variables into the map, you simply call the Map's put() method:
myVariables.put("A", Integer.valueOf(100));
myVariables.put("B", Integer.valueOf(200));
myVariables.put("C", Integer.valueOf(300));
Retrieving the value of a variable is as simple as using the get() method with your variable name as the key:
int val = myVariables.get("A").intValue();
Notice that I have chosen to box and unbox the primitive int values myself rather than rely on autoboxing. This is just a personal choice. It does trade off conciseness, but I'd rather see what's actually happening.
In my opinion, using reflection to determine a class field to access dynamically at run time is wholly unsatisfactory and should be avoided ... most especially since using the Java Collections API enables a statically typed, type safe solution that can be checked at compile time.
You can't check for a variable's name. For more information look here, there are some good answers:
Java Reflection: How to get the name of a variable?
But maybe a HashMap can help you, where you store "A", "B", "C" as keys and the respective numbers as value.
edit: Okay, maybe with something like this http://docs.oracle.com/javase/6/docs/api/java/lang/reflect/Field.html it could be possible.
I have an enum like that:
public enum Lang {
TR("tr"),
EN("en"),
SE("se");
private String langName;
private Lang(String langName) {
this.langName = langName;
}
}
at another class I want to check whether a langName exists or not. If I put a getter method I can iterate over langNames:
for (Lang langEnum : Lang.values()) {
langEnum.getLangName();
}
However my enum may be too long and I don't want to iterate over an array. I want to use a Map or Set. On the other hand I don't want to another variable within my enum.
How can I check whether my enum has a langName or not?
Well, if every enum constant represents a language (as the code seems to suggest), then I would use an EnumSet.
Set<Lang> langs = EnumSet.allOf(Lang.class);
And then I can check if a language is already there. Like
if(langs.contains(Lang.EN) {
//...
}
Not sure if this is the answer you were looking for. The contains method of EnumSet would not even iterate over the internal collection. The internal collection would be stored in an array and finding an element is calculated based on a hash. So, this in fact, should achieve what you requested in the question.
How about using valueOf?
Lang lang = null;
try {
lang = Lang.valueOf(enumName);
// enum exists
} catch (IllegalArgumentException e) {
// enum does not exist
}
Since your enum name is just the language name capitalized, you can just capitalize the language name and pass it into valueOf.
My enum is like this currently:
public enum Manufacturers {
Honda,
GM,
Toyota,
Ferrari
}
I need to create a Hashmap so I plan on doing this, is this correct?
Manufacturers mfg = Manufacturers.Honda;
mfg.ordinal() // save as key
i.e. I will store the key using the enumInstance.ordinal()
Also, I need to be able to parse a string which will be the ordinal value of the enumeration, and get an enum back:
Manufacturers mfg = Manufacturers.valueOf(mfgOrdinalValueAsString);
The above gave me an error (the string was "1"). Is this the correct way? I guess I should have a try/catch in there right?
The .valueOf would actually be expecting the String "GM" (for 1).
As for storing your enum values in a map, use EnumMap which is designed specifically for this - and will be fast at it, too.
If you really wanted to reference a value by its ordinal, use something like Manufacturers.values()[1].
A suggestion: better use name() to get the name of the enum as a String, and whenever you need to get back the original Enum from it, use the valueOf() method - since valueOf() expects the name, not the ordinal, as a parameter. For example:
enum Example {ONE, TWO};
String name = Example.ONE.name();
Example e = Example.valueOf(Example.class, name); // e has value ONE
If you definitely need to use the ordinal, the ordinal() method will return an index which you can use to retrieve the respective Enum from the array returned by the values() method. Like this:
int ordinal = Example.ONE.ordinal();
Example e = Example.values()[ordinal]; // e has value ONE
As has already been pointed out, consider using EnumMap, as stated in the documentation, it is
A specialized Map implementation for use with enum type keys. All of the keys in an enum map must come from a single enum type that is specified, explicitly or implicitly, when the map is created. Enum maps are represented internally as arrays. This representation is extremely compact and efficient.
EDIT
If you need to associate a different code to each element of the enum (other than its automatically assigned ordinal), you can always add it as an attribute to the enum, together with getters and setters, like this:
public enum Manufacturers {
Honda(10),
GM(20),
Toyota(30),
Ferrari(40);
private int code;
Manufacturers(int code) {
this.code = code;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
For example:
Manufacturers m = Manufacturers.Honda;
System.out.println(m.getCode()); // prints 10
m.setCode(100);
System.out.println(m.getCode()); // prints 100
Just be aware that you won't be able to reconstruct an Enum object from the code attribute, since that was defined by the programmer.