I am using enumeration with switch case but I am getting the following error:
NEWS FEED is not a constant in FragmentName
This is my enum string constant,
public enum FragmentName{
FRAGMENT_NEWSFEED("NEWS FEED"),
FRAGMENT_MESSAGES("MESSAGES"),
FRAGMENT_EVENTS("EVENTS"),
FRAGMENT_WHOISAROUDNME("WHOS AROUND");
private final String text;
private FragmentName(final String text) {
this.text = text;
}
#Override
public String toString() {
return text;
}
}
//This is my function from where i check for corresponding enum constant
public void changeTitle(String title) {
switch (Enums_String.FragmentName.valueOf(title)) {
case FRAGMENT_NEWSFEED:
System.out.println("1");
break;
case FRAGMENT_EVENTS:
System.out.println("2");
break;
case FRAGMENT_MESSAGES:
System.out.println("3");
break;
case FRAGMENT_WHOISAROUDNME:
System.out.println("4");
break;
}
}
When I call
changeTitle("NEWS FEED");
it creates an exception in the changeTitle function even the value passed is same, so any help would be appreciated as I have tried my every effort to solve this.
Add this code to your enum
private static final Map<String, FragmentName> map = new HashMap<>();
static {
for (FragmentName en : values()) {
map.put(en.text, en);
}
}
public static FragmentName valueFor(String name) {
return map.get(name);
}
Now instead of valueOf use valueFor
switch (Enums_String.FragmentName.valueFor(title))
// ^^^^^^^^
The valueOf
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.
What you want do id get the enum by a member value for that you have write a function to do so like fromString below
public enum FragmentName {
FRAGMENT_NEWSFEED("NEWS FEED"),
FRAGMENT_MESSAGES("MESSAGES"),
FRAGMENT_EVENTS("EVENTS"),
FRAGMENT_WHOISAROUDNME("WHOS AROUND");
private final String text;
private FragmentName(final String text) {
this.text = text;
}
#Override
public String toString() {
return text;
}
public static FragmentName fromString(String value) {
for (FragmentName fname : values()) {
if (fname.text.equals(value)) {
return fname;
}
}
return null;
}
}
and replace your switch case like
switch (FragmentName.fromString(title)) {
Create a method like this :
public static FragmentName getFragmentNameByText(String text) {
for (FragmentName fragment : values()) {
if (fragment.text.equals(text)) {
return fragment;
}
}
return null;
}
and call this instead of valueOf().
You can change your function to compare the string values passed in:
public void changeTitle(String title) {
if(title.equals(FRAGMENT_NEWSFEED.toString())) {
System.out.println("1");
} else if(title.equals(FRAGMENT_MESSAGES.toString())) {
System.out.println("2");
} else if(title.equals(FRAGMENT_EVENTS.toString())) {
System.out.println("3");
} else if(title.equals(FRAGMENT_WHOISAROUDNME.toString())) {
System.out.println("4");
} else {
// throw an error
}
}
You can't operate an switch off of a function call, so you have to use an if-else block.
Related
I'm newbie in using generic in java, i have simple method that i would like to return any type from that, this method return other class getters methods, for example i have channels class and that have getChannelId() method, i want to return that from this method:
#SuppressWarnings("unchecked")
public <T extends Channels> T getChannelColumn(ChannelContentModel.channelColumns column) {
switch (column) {
case id:
return (T) channel.getId();
break;
case title:
return (T) channel.getChannelTitle();
break;
}
return null;
}
getId is int and getChannelTitle is string, how can i fix this method to return any type?
in my code channel is instance of Channels class, Thanks in advance
As commented by #Geckstar;
Java is statically typed
But it is possible to clear your code sample from compile errors.
Remove breaks, because there is no need to break after return statement.
extend return type from object. T extends Object instead T extends Channel
id must be Integer, not int or change to (T)(Integer) channel.getId()
This is not a good solution, it only fixes compile errors.But this method's usage may cause runtime failures.
#SuppressWarnings("unchecked")
public <T extends Object> T getChannelColumn(ChannelContentModel.channelColumns column) {
switch (column) {
case id:
return (T) channel.getId(); //int must be Integer
case title:
return (T) channel.getChannelTitle();
}
return null;
}
You can create property wrapper which will hold the value in string data format when required it will convert to a specific data type.
public class MyProperty {
private String stringVal;
public MyProperty(String stringVal) {
this.stringVal = stringVal;
}
public Integer getInteger() throws IllegalArgumentException {
return integerValue.getValue();
}
public String getString() {
return stringValue.getValue();
}
private PropertyValue<String> stringValue = new PropertyValue<String>() {
protected String parse(String rep) {
return rep;
}
};
private PropertyValue<Integer> integerValue = new PropertyValue<Integer>() {
protected Integer parse(String rep) throws NumberFormatException {
return Integer.valueOf(rep);
}
};
private abstract class PropertyValue<T> {
private T value;
protected abstract T parse(String rep) throws Exception;
public T getValue() throws IllegalArgumentException {
try {
value = (stringValue == null) ? null : parse(stringVal);
} catch (Exception e) {
value = null;
}
return value;
}
}
}
you can make specialize class or one class having the access method to get the value with specified data type
#SuppressWarnings("unchecked")
public MyProperty getChannelColumn(ChannelContentModel.channelColumns column) {
switch (column) {
case id:
return new MyProperty(channel.getId());//
break;
case title:
return new MyProperty(channel.getChannelTitle());
break;
}
return null;
}
I decided to get into more JAVA and I noticed in OCA 7 that an enum can declare a method which overrides another method. See this enum:
enum CoffeeSize {
BIG(),
HUGE(),
OVERWHELMING() {
public String getLidCode() { // This method overrides the following method with similar name.
return 'A';
}
}; // <--- is this semicolon I should be looking for?
CoffeeSize(ounces) {
this.ounces = ounces;
}
private int ounces;
public int getOunces() {
return ounces;
}
public String getLidCode() {
return 'B';
}
}
My question is in which case does a method in a enum override another method. Is it the method preceding the semicolon that overrides or what's the rule here?
Thanks for your time.
The constants act similar to anonymous classes, where the enum itself is the abstract base class:
abstract class CoffeeSize {
CoffeeSize(int ounces) {
this.ounces = ounces;
}
private int ounces;
public int getOunces() {
return ounces;
}
public String getLidCode() {
return "B";
}
}
CoffeeSize OVERWHELMING = new CoffeeSize(3) {
#Override
public String getLidCode() {
return "A";
}
};
You can override the base implementation with any constant, not just the one before the semicolon:
enum CoffeeSize {
BIG(1){
#Override
public String getLidCode() {
return "C";
}
},
HUGE(2) {
#Override
public String getLidCode() {
return "B";
}
},
OVERWHELMING(3) {
#Override
public String getLidCode() {
return "A";
}
};
...
}
In the above, all the constants override getLidCode with a different implementation. The semicolon just marks the end of the list of constants.
How can I return enums like this?
Before I was returing an int with 0 if no, 1 if yes and 2 if other. But this wasn't good way to do. So how should it be done. My code:
class SomeClass{
public enum decizion{
YES, NO, OTHER
}
public static enum yourDecizion(){
//scanner etc
if(x.equals('Y')){
return YES;
}
else if (x.equals('N')){
return NO;
}
else{
return OTHER;
}
}
}
I don't what the "//scanner etc." does, but the methods return type should be decizion:
public static decizion yourDecizion() { ... }
Furthermore, you can add the Y, N, etc. values to the enum constants:
public enum decizion{
YES("Y"), NO("N"), OTHER;
String key;
decizion(String key) { this.key = key; }
//default constructor, used only for the OTHER case,
//because OTHER doesn't need a key to be associated with.
decizion() { }
static decizion getValue(String x) {
if ("Y".equals(x)) { return YES; }
else if ("N".equals(x)) { return NO; }
else if (x == null) { return OTHER; }
else throw new IllegalArgumentException();
}
}
Then, in the method, you can just do:
public static decizion yourDecizion() {
...
String key = ...
return decizion.getValue(key);
}
I think you should do something like these, an enum class. Then you can add as many types you want and the method yourDecizion() will return the enum type depending on the given parameter.
public enum SomeClass {
YES(0),
NO(1),
OTHER(2);
private int code;
private SomeClass(int code) {
this.code = code;
}
public int getCode() {
return code;
}
public static SomeClass yourDecizion(int x) {
SomeClass ret = null;
for (SomeClass type : SomeClass.values()) {
if (type.getCode() == x)
ret = type;
}
return ret;
}
}
Change your code to:
class SomeClass{
public enum decizion {
YES, NO, OTHER
}
public static decizion yourDecizion(){
//scanner etc
if(x.equals('Y')){
return decizion.YES;
}
else if (x.equals('N')){
return decizion.NO;
}
else{
return decizion.OTHER;
}
}
}
Note: The method return type must be decizion instead of enum and decizion should have an upper case name (as all classes should).
You can get the value in below way. Here you have private constructor which will initialize the value you want to set and when the instance method value gets invoked simply return this.key.
public class Application {
enum Day {
MONDAY("Monday"), TUESDAY("Tuesday");
String key;
Day(String str) {
key = str;
}
public String value() {
return this.key;
}
}
public static void main(String[] args) {
System.out.println(Day.MONDAY.value());
}
}
I want to have something like this below (example how I would do this in C#), to get typed value from SQLiteDB:
private T GetValueFromDB<T>(String colName) {
object returnValue = null;
switch (typeof(T)) {
case Boolean:
returnValue = dbData.getInt(colName) == 1;
break;
case Int32:
returnValue = dbData.getInt(colName);
break;
case Int64:
returnValue = dbData.getLong(colName);
break;
case String:
returnValue = dbData.getString(colName);
break;
}
return (T)returnValue;
}
Is there a possibility (with switch case or if else) to implement it in Java?
If you already know the type when calling the method, you could do something like this:
private T GetValueFromDB<T>(String colName, Class<T> returnType) {
if(returnType.equals(Boolean.class)) {
return (T)(dbData.getInt(colName) == 1);
} else if(returnType.equals(Int32.class)) {
// and so on
}
}
Java uses type erasure so it is impossible to determine type of T at runtime.
I have made inteface switch, maybe it can be useful for someone :
new ISwitch(pagerCtrl.getPager().getFragmentByID(fragment_id))
.addCase(new ISwitch.CaseListener<Type1>() {
#Override
public void Case(Type1 instance) {
}
}).addCase(new ISwitch.CaseListener<Type2>() {
#Override
public void Case(Type2 instance) {
}
}).addDefault(new ISwitch.DefaultListener() {
#Override
public void Default() {
}
}).build();
public class ISwitch {
public interface CaseListener<T> {
void Case(T instance);
}
public interface DefaultListener {
void Default();
}
Object value;
LinkedList<CaseListener<?>> col = new LinkedList<>();
DefaultListener defaultListener;
public ISwitch(Object value) {
this.value = value;
}
public void build() {
boolean wasNotifiedMinimumOnce = false;
for (CaseListener<?> c : col) {
try {
CaseListener<Object> l = (CaseListener<Object>) c;
l.Case(value);
wasNotifiedMinimumOnce = true;
break;
} catch (ClassCastException e) {
}
}
if ( !wasNotifiedMinimumOnce ) {
if ( defaultListener != null ) {
defaultListener.Default();
}
}
}
public ISwitch addCase(CaseListener<?> caseListener) {
col.add(caseListener);
return this;
}
public ISwitch addDefault(DefaultListener defaultListener) {
this.defaultListener = defaultListener;
return this;
}
}
The small drawback of implementation is that we cant make check instanceof, that why i catch it on cast. For me its not big deal, but it can be performance issue on java server code executed XXXXXX times each seconds.
Given the following java enum:
public enum AgeRange {
A18TO23 {
public String toString() {
return "18 - 23";
}
},
A24TO29 {
public String toString() {
return "24 - 29";
}
},
A30TO35 {
public String toString() {
return "30 - 35";
}
},
}
Is there any way to convert a string value of "18 - 23" to the corresponding enum value i.e. AgeRange.A18TO23 ?
Thanks!
The best and simplest way to do it is like this:
public enum AgeRange {
A18TO23 ("18-23"),
A24TO29 ("24-29"),
A30TO35("30-35");
private String value;
AgeRange(String value){
this.value = value;
}
public String toString(){
return value;
}
public static AgeRange getByValue(String value){
for (final AgeRange element : EnumSet.allOf(AgeRange.class)) {
if (element.toString().equals(value)) {
return element;
}
}
return null;
}
}
Then you just need to invoke the getByValue() method with the String input in it.
You could always create a map from string to value - do so statically so you only need to map it once, assuming that the returned string remains the same over time. There's nothing built-in as far as I'm aware.
According to effective java (2nd ed) item 30, it can be (it is much faster than the loop)
public enum AgeRange {
A18TO23("18-23"),
A24TO29("24-29"),
A30TO35("30-35");
private final String value;
AgeRange(String value){
this.value = value;
}
#Override public String toString(){
return value;
}
private static final Map<String, AgeRange> stringToEnum =
new HashMap<String, AgeRange>();
static {
for (AgeRange r : values()) {
stringToEnum.put(r.toString(), r);
}
}
public static AgeRange getByValue(String value){
return stringToEnum.get(value);
}
}
for (AgeRange ar: EnumSet.allOf(AgeRange)) {
if (ar.toString().equals(inString)) {
myAnswer = ar;
break;
}
}
Or something like that? Just typed in, haven't run through a compiler. Forgive (comment on) typos...
Or use logic like this to build a map once. Avoid iteration at runtime. Good idea, Jon.
The class overrides "toString()" - so, to get the reverse operation, you need to override valueOf() to translate the output of toString() back to the Enum values.
public enum AgeRange {
A18TO23 {
public String toString() {
return "18 - 23";
}
public AgeRange valueOf (Class enumClass, String name) {
return A18T023
}
},
.
.
.
}
Buyer beware - uncompiled and untested...
The mechanism for toString() and valueOf() is a documented part of the API
You could try something like the following?
static AgeRange fromString(String range) {
for (AgeRange ageRange : values()) {
if (range.equals(ageRange.toString())) {
return ageRange;
}
}
return null;
}
Or, as others suggested, using a caching approach:
private static Map<String, AgeRange> map;
private static synchronized void registerAgeRange(AgeRange ageRange) {
if (map == null) {
map = new HashMap<String, AgeRange>();
}
map.put(ageRange.toString(), ageRange);
}
AgeRange() {
registerAgeRange(this);
}
static AgeRange fromString(String range) {
return map.get(range);
}