I've class Aligment like below:
public enum Aligment
{
Evil,
Neutral,
Good,
Undefined
}
And I want to use these values in switch like so:
System.out.print("Choose you'r start up character" +
"1.Good" +
"2.Evil" +
"3.Neutral");
//1 string alignmentChoice = scan.nextLine();
//2 Aligment alignmentChoice = Aligment.Undefined;
switch( aligmentChoice )
{
case Good:
alignment = Aligment.Good;
break;
case Evil:
alignment = Aligment.Evil;
break;
case Neutral:
alignment = Aligment.Neutral;
break;
default:
System.out.println("How did you manage to get here? You have broke the system.");
break;
}
And I'm not sure how to use it like //1 or //2. Thanks for help in advance.
Use it like so :
switch(Aligment.valueOf(alignmentChoise)) {
case Evil:
alignment = Aligment.Evil;
break;
}
Note :
This will throw IllegalArgumentException if the enum constant is not found.
If you refactor and move this switch case logic to a method in your enum, you no longer need to use a switch statement for getting an enum from a string.
In the following example, I have added a method fromString() which will take a string input name, and compare with all of our enum values (case unsensitive).
If a matching value is not found, we throw an IllegalArgumentException.
Here is the example:
public class AlignmentTest{
public static void main(String[] args){
String good = "good";
String neutral = "NEUTRAL";
String evil = "EvIl";
String unknown = "unknown";
Alignment alignment1 = Alignment.fromString(good);
System.out.println("Alignment 1: " + alignment1);
Alignment alignment2 = Alignment.fromString(neutral);
System.out.println("Alignment 2: " + alignment2);
Alignment alignment3 = Alignment.fromString(evil);
System.out.println("Alignment 3: " + alignment3);
Alignment alignment4 = Alignment.fromString(unknown);
System.out.println("Alignment 4: " + alignment4);
}
public enum Alignment {
EVIL("Evil"),
NEUTRAL("Neutral"),
GOOD("Good");
private String name;
Alignment(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public static Alignment fromString(String name) {
for (Alignment alignment : Alignment.values()) {
if (alignment.name.equalsIgnoreCase(name)) {
return alignment;
}
}
throw new IllegalArgumentException("No alignment with name " + name + " found");
}
}
}
This outputs the following:
Alignment 1: GOOD
Alignment 2: NEUTRAL
Alignment 3: EVIL
Exception in thread "main" java.lang.IllegalArgumentException: No alignment with name unknown found
at AlignmentTest$Alignment.fromString(AlignmentTest.java:44)
at AlignmentTest.main(AlignmentTest.java:19)
Create a mapping (static map) inside your enum for holding the map between the name to be provided by the user to the enum.
public enum Alignment {
Evil("Evil"),
Neutral("Neutral"),
Good("Good"),
Undefined("Undefined");
private static final Map<String, Alignment> MAPPINGS = new HashMap<>();
static {
for (Alignment alignment : Alignment.values()) {
MAPPINGS.put(alignment.getName(), alignment);
}
}
private String name;
Alignment(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Alignment getAlignmentForName(String name) {
return MAPPINGS.get(name);
}
Now, you can use getAlignmentForName to map the user input to an enum. It will return null for invalid values.
The advantage of this is that you need not change any code when you add a new enum instance... In your case, an appropriate switch case has to be added.
Note: The names of enum fields must be in uppercase letters as per the conventions.
Related
I have these integers and this method which uses constructors but I am supposed to change this into an Enum since thise code is outdated. I do understand how Enums work in theory but no matter what I try to change I do it wrong.
public static final int CHILDRENS = 2;
public static final int REGULAR = 0;
public static final int NEW_RELEASE = 1;
private Price price;
public void setPriceCode(int priceCode) {
switch (priceCode) {
case REGULAR:
price = new RegularPrice();
break;
case CHILDRENS:
price = new ChildrensPrice();
break;
case NEW_RELEASE:
price = new NewReleasePrice();
break;
default:
throw new IllegalArgumentException("Incorrect Price Code");
}
}
I thaught that to change to enums I should first delete the given integers at the top and then add this before the method:
enum cases {
REGULAR, CHILDRENS, NEW_RELEASE;
}
And now I do not know how to change the method's code accordingly.
How do I give the cases the integers, should I not delete these: ?
public static final int CHILDRENS = 2;
How should I change my switch case accordingly?
Would really appreciate some help, I watched a bunch of videos on enums but the cases were very different.
Do it like this:
enum PriceCode {
REGULAR(0), // calls constructor with value 0
NEW_RELEASE(1), // calls constructor with value 1
CHILDREN(2) // calls constructor with value 2
;
private final int priceCode;
private PriceCode(int priceCode) {
this.priceCode = priceCode;
}
int value() {
return priceCode;
}
}
public class Main {
// Usage
public static void setPriceCode(PriceCode priceCode) {
System.out.println("The value of " + priceCode + " is " + priceCode.value());
switch (priceCode) {
case REGULAR:
// Do something
break;
case CHILDREN:
// Do something
break;
case NEW_RELEASE:
// Do something
break;
default:
throw new IllegalArgumentException("Incorrect Price Code");
}
}
public static void main(String[] args) {
// Set price code as CHILDREN
setPriceCode(PriceCode.CHILDREN);
// Another sample usage
System.out.println("Price code of NEW_RELEASE is " + PriceCode.NEW_RELEASE.value());
}
}
Output:
The value of CHILDREN is 2
Price code of NEW_RELEASE is 1
Learn more about enum and enum constructor at Java tutorial by Oracle.
Think of an enum as a class or interface, in other words it is a type. I recommend the following tutorial: Enum Types And according to java coding conventions, names of types should begin with a capital letter. Therefore, in the below code, I changed the name of the enum to Cases.
Hence the parameter to method setPriceCode should be Cases. The rest of the code remains the same.
enum Cases {
REGULAR, CHILDRENS, NEW_RELEASE;
}
private Price price;
public void setPriceCode(Cases priceCode) {
switch (priceCode) {
case REGULAR:
price = new RegularPrice();
break;
case CHILDRENS:
price = new ChildrensPrice();
break;
case NEW_RELEASE:
price = new NewReleasePrice();
break;
default:
throw new IllegalArgumentException("Incorrect Price Code");
}
}
Here is an example call to method setPriceCode()
setPriceCode(Cases.CHILDRENS);
I have the following code :
class MyClass {
private Value value;
public enum Value {
INSERT_ONLY("INSERT_ONLY"), UPDATE_ONLY("UPDATE_ONLY"), UPSERT("UPSERT") ;
private final String val ;
private Value(final String v) {val = v ;}
public String toString() {return val ;}
public String getVal() {
return val;
}
} ;
public Value getValue() {
return value;
}
public void setValue(Value value) {
this.value = value;
}
}
public class one {
public static void main(String[] args) {
MyClass obj = new MyClass() ;
obj.setValue(MyClass.Value.INSERT_ONLY) ;
String s = obj.getValue().toString() ;
String s1 = MyClass.Value.INSERT_ONLY.toString() ;
switch(s) {
case "INSERT_ONLY" : System.out.println("INSERT_ONLY") ;
break ;
case "s2" : System.out.println("s2") ;
break ;
}
}
}
This code works. But what I want is that in switch-case I use the strings as defined in the enum Value. If I use s1 in case, it generates an error. What is the way out?
Enums have a method .name() that returns the enum as a String. All your "values" are equivalent to this - just switch on that.
You can delete the value field, the constructor and getter and call name() where you are currently calling getValue().
Further, the default implementation of toString() returns name() so you can delete your toString() method without having any effect.
Finally, you can switch on the enum itself.
you string in the enum is actually the same as the enumertor constants... so it is a little redundant and completely unnescessary...
try this:
enum Value {
INSERT_ONLY, UPDATE_ONLY, UPSERT;
}
public static void main(String[] args) {
Week obj = new Week() ;
Value s = obj.getValue( ) ;
switch(s) {
case INSERT_ONLY : System.out.println("INSERT_ONLY") ;
break ;
case UPDATE_ONLY : System.out.println("UPDATE_ONLY") ;
break ;
}
}
}
You could try it this way:
MyClass.Value value = obj.getValue() ;
switch(value) {
case INSERT_ONLY : System.out.println("INSERT_ONLY") ;
break ;
case UPSERT : System.out.println("Upsert") ;
break ;
case UPDATE_ONLY : System.out.println("Update only") ;
break ;
}
Basically, the switch-statement uses the enum-names. So there is no need to apply the toString()-method on the Value returned by obj.getValue().
If you would like to know why switch will not work in combination with strings, please have a look here.
One more suggestion: add also the default-branch to the switch-statement.
If I understand correctly, you're trying to look up an enum constant by an unknown string s. The reason your case expression can't be s1 is because it must be a compile-time constant, which s1 is not. Since your example seems to be mostly theoretical, I'll suggest a few options and you can pick the most appropriate for your actual case:
Assuming the enum names are the same as their values (in which case you can scrap the field entirely) and you're just trying to look up an enum by its name, just do this:
MyClass.Value v = MyClass.Value.valueOf(s);
This will throw an IllegalArgumentException if no mapping is found for s1.
Still assuming the names are the same, but you do need an actual switch with some additional cases and custom logic:
try {
MyClass.Value v = MyClass.Value.valueOf(s);
switch (v) {
case INSERT_ONLY : System.out.println("INSERT_ONLY") ;
break ;
}
} catch (IllegalArgumentException e) {
switch (s)
case "s2" : System.out.println("s2") ;
break ;
}
}
If the names are not actually the same, you can add a static map of constants inside the enum class, to simulate valueOf():
public enum Value {
ONLY_INSERT("ONLY_INSE"), ONLY_UPDATE("UPDATE_ONLY"), UPSERT("UPSERT") ;
private static final Map<String, Value> byName = new HashMap<>();
static {
for (Value v : values()) {
byName.put(v.getVal(), v);
}
}
public static Value byName(String name) {
Value result = byName.get(name);
if (result == null) {
throw new IllegalArgumentException("Invalid name" + name);
}
return result;
}
private final String val ;
private Value(final String v) {val = v ;}
public String toString() {return val ;}
public String getVal() {
return val;
}
} ;
Now you can do the same as the previous solutions, using MyClass.Value.byName().
I guess I did not yet get the concept of Enums in Java.
I try to compare Strings to my Enum-entries comparable to Special characters in an enum.
package com.stackoverflow.tests;
public class EnumTest {
enum EnumTestOperator {
EQUAL("=="),
NOT_EQUAL("!=");
private String value;
private EnumTestOperator(String value) {
this.value = value;
}
public String toString() {
// will return == or != instead of EQUAL or NOT_EQUAL
return this.value;
}
}
public static void main(String[] args) {
String line;
line = "<>";
line = ".ne.";
line = "!=";
// Operator
switch(line) {
// case "!=":
case EnumTestOperator.NOT_EQUAL:
System.out.println("Not Equal");
break;
default:
System.out.println("Something else");
break;
}
}
}
But in the Line:
case EnumTestOperator.NOT_EQUAL:
I get a compiler error:
Type mismatch: cannot convert from EnumTest.EnumTestOperator to String
What am I doing wrong?
You are comparing incompatible types. It's similar to the statement
"some string" == EnumTestOperator.NOT_EQUAL
where your compare a string value to an enum constant.
Just stop using enums and declare them as string constants:
private static final String EQUAL = "==";
private static final String NOT_EQUAL = "!=";
Then you can use them in the switch/case.
The other solution would be to find the enum constant based on your input. Add this to your enum:
public static EnumTestOperator byValue(String val){
for(EnumTestOperator en:values()){
if(en.value.equals(val)){
return en;
}
}
return null;
}
And then use the function like this:
EnumTestOperator en = EnumTestOperator.byValue(line);
switch(en) {
case NOT_EQUAL:
System.out.println("Not Equal");
break;
default:
System.out.println("Something else");
break;
}
Unfortunately you will have to handle the null case differently since putting a null into a switch will throw a NullPointerException.
EnumTestOperator.NOT_EQUAL is an instance of EnumTestOperator. You cannot compare it with a String.
You can evenutually compare EnumTestOperator.NOT_EQUAL.toString() with a String but not in a case statement (case statements require constant expressions in Java).
But you can instead iterate on EnumTestOperator constants :
public static EnumTestOperator find(String strValue) {
for(EnumTestOperator operator : EnumTestOperator.values()) {
if(operator.toString().equals(strValue)) {
return operator;
}
}
throw new IllegalArgumentException("No matching value");
}
I'd like to point out that I'm very new to Java, which is why I may be making stupid mistakes.
I have a class called "Characters", which consists of 4 variables and multiple methods. All variables are private, so from what I've read, I need to use methods to do anything to them.
One of the methods is supposed to return one of the variables in string form, however I keep getting an error from both eclipse and when I run it. "This method must return a result of type "String". The error occurs on the first line of the method:
public String displayStats(String option) {
switch (option) {
case "charName":
System.out.println(charName);
return charName;
case "charHealth":
System.out.println(charHealth);
String charHealth2 = Integer.toString(charHealth);
return charHealth2;
case "charMana":
System.out.println(charMana);
String charMana2 = Integer.toString(charMana);
return charMana2;
case "charStamina":
System.out.println(charStamina);
String charStamina2 = Integer.toString(charStamina);
return charStamina2;
default:
System.out.println("Error on default");}
}
}
The full class:
package basics;
public class Characters {
private String charName = "";
private int charHealth = 0;
private int charMana = 0;
private int charStamina = 0;
public void summoner(Characters player) {
player.charName = "Summoner";
player.charHealth = 80;
player.charMana = 150;
player.charStamina = 50;}
public void sentinel(Characters player) {
player.charName = "Sentinel";
player.charHealth = 200;
player.charMana = 50;
player.charStamina = 100;}
public void beserker(Characters player) {
player.charName = "Beserker";
player.charHealth = 100;
player.charMana = 0;
player.charStamina = 200;}
public void mage(Characters player) {
player.charName = "Mage";
player.charHealth = 80;
player.charMana = 200;
player.charStamina = 20;}
public String displayStats(String option) {
switch (option) {
case "charName":
System.out.println(charName);
return charName;
case "charHealth":
System.out.println(charHealth);
String charHealth2 = Integer.toString(charHealth);
return charHealth2;
case "charMana":
System.out.println(charMana);
String charMana2 = Integer.toString(charMana);
return charMana2;
case "charStamina":
System.out.println(charStamina);
String charStamina2 = Integer.toString(charStamina);
return charStamina2;
default:
System.out.println("Error on default");}
}
}
You aren't returning anything in the default case of your switch statement, which means that there is a possibility (however small) that the method won't know what to return.
In the displayStats function you don't return a String in all paths of your code.
This is because the default doesn't return at all.
Maybe you wanted to write:
default:
return "Error on default";
Two problems: charName is a string, but charHealth, charMana, and charStamina are ints. Thus, your displayStats function isn't always returning a string.
Also, your default option in your switch statement should return a string as well.
It would be better to create an accessor function for each variable:
public String getCharName() {
return charName;
}
public int getCharHealth() {
return charHealth;
}
etc.
The method displayStats must always return a String or throw an exception. Since the code implies that the default case is an error, then throw an exception. At this point rather than create a new class of exception, just throw an IllegalArgumentException -- new IllegalArgumentException(option). When printed out it will state the type of exception and the value of the invalid option.
I have a number of Java classes I need to convert to Swift code.
One of the classes has an advanced enum:
public enum Student {
STUDENT_ONE("Steve", "Jobs")
STUDENT_TWO("Tim", "Cook")
private String _firstName;
private String _lastName;
}
How can I replicate the same behavior in Swift?
After some thought, I agree with godmoney that aksh1t's solution is better that my solution using Strings.
Anyway, here is a more concise variant of aksh1t's solution, using only one computed property returning a tuple: (tested in Swift 2.0)
enum Student {
case STUDENT_ONE, STUDENT_TWO
typealias Details = (firstName: String, lastName: String)
var details : Details {
switch(self) {
case STUDENT_ONE : return ("Steve", "Jobs")
case STUDENT_TWO : return ("Tim", "Cook")
}
}
}
// Usage:
func test(sd: Student.Details) {
print(sd.firstName)
print(sd.lastName)
}
test(Student.STUDENT_ONE.details)
I was trying to do the same thing with converting Java code to Swift, and ended up doing something like this :
public enum Student {
case STUDENT_ONE
case STUDENT_TWO
var firstName: String {
get {
switch self {
case .STUDENT_ONE:
return "Steve"
case .STUDENT_TWO:
return "Tim"
}
}
}
var lastName: String {
get {
switch self {
case .STUDENT_ONE:
return "Jobs"
case .STUDENT_TWO:
return "Cook"
}
}
}
}
Now, this is really long and messy and I'm not really sure whether this is the right way to do it, but I couldn't find anything else that worked. I would love to know if there is some other better way to do it.
This is what I ended up doing - not sure about this at all:
struct Students {
enum Students {
case STUDENT_ONE(String, String)
case STUDENT_TWO(String, String)
}
let STUDENT_ONE = Students.STUDENT_ONE("Steve", "Jobs")
let STUDENT_TWO = Students.STUDENT_TWO("Steve", "Two")
}
Enums are not necessarily the best choice to represent this type of data. I choose structs and this works well, using the correct accessors:
public struct Student {
public let firstName : String
public let lastName : String
public static let STUDENT_ONE = Student(firstName: "Steve", lastName: "Jobs")
public static let STUDENT_TWO = Student(firstName: "Tim", lastName: "Cook")
}
Moved here from another question marked as a duplicate so the variable names don't match up exactly, however, the concepts all do.
The most obvious way would be:
public enum EnumWeapon {
case WOODEN_SWORD
case STONE_SWORD
case STEEL_SWORD
func getName() -> String {
switch self {
case WOODEN_SWORD: return "Wooden Sword"
case STONE_SWORD: return "Stone Sword"
case STEEL_SWORD: return "Steel Sword"
}
}
func getDamage() -> Int {
switch self {
case WOODEN_SWORD: return 4
case STONE_SWORD: return 6
case STEEL_SWORD: return 8
}
}
}
If you have a single value to associate with each enum case, you can use the raw value syntax, or just use it to simplify the enum case above:
public enum Weapon : Int {
case WOODEN_SWORD = 4
case STONE_SWORD = 6
case STEEL_SWORD = 8
func getDamage() -> Int {
return rawValue
}
func getName() -> String {
switch self {
case .WOODEN_SWORD: return "Wooden Sword"
case .STONE_SWORD: return "Stone Sword"
case .STEEL_SWORD: return "Steel Sword"
}
}
}
Obviously, if you don't need the name, you can omit the getName function. Likewise you can omit the getDamage function and just use weapon.rawValue
An even simpler way, and yet more analogous to the actual Java implementation, would be to use a struct instead of an enum, as:
public struct Weapon {
public let name : String
public let damage : Int
private init(name:String, damage:Int) {
self.name = name
self.damage = damage
}
public static let WOODEN_SWORD = Weapon(name: "Wooden Sword", damage: 4)
public static let STONE_SWORD = Weapon(name: "Stone Sword", damage: 6)
public static let STEEL_SWORD = Weapon(name: "Steel Sword", damage: 8)
}
and, be redefining operator ==, you can get equality comparisons:
func == (lhs:Weapon, rhs:Weapon) -> Bool {
return lhs.name == rhs.name && lhs.damage == rhs.damage
}
and, by redefining operator ~= you can get switch to work as expected:
func ~= (lhs:Weapon, rhs:Weapon) -> Bool {
return lhs == rhs
}
func test(sword:Weapon) {
switch sword {
case Weapon.STONE_SWORD: print("stone")
default: print("something else")
}
}
test(Weapon.STONE_SWORD)
A whole lot of options, mostly it just depends on what you're really trying to do and how much data you need to wrap in the enum.