How to change from Constructors to Enum in java? - java

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);

Related

How to clean up code with too many if/else java

I am making something right now that gives you an item based on a command and it's input.
If the command is
/item mythical destroyer or /item mythical 1 (an ID system)
it gives you a destroyer item (arbitrary, don't worry about the specifics).
Looking at other questions, they all have to do with enums, but what I am looking for is how to do it with integers and strings.
Here is what I am doing right now:
interface MythicalItem {
ItemStack getItem();
int getPrice();
void setPrice(int var1);
int getID();
}
class DestroyerMI implements MythicalItem {
private int price = 50;
int getID(){
return 1;
}
void setPrice(int var1){
this.price = var1;
}
int getPrice(){
return price;
}
Item getItem(){
Item item = new Item()
return item;
}
}
class MythicalUtil{
public static ItemStack parseItem(MythicalItem mythicalItem){
return mythicalItem.getItem();
}
public static int parseID(MythicalItem mythicalItem){
return mythicalItem.getID();
}
public static int parsePrice(MythicalItem mythicalItem){
return mythicalItem.getPrice();
}
}
My problem arises right here, and it doesn't seem like there is a way to get the mythical item by name/id without a giant switch or if/else, which I am trying to prevent.
// String[] args = {"mythical", "destroyer"};
if(args[0].equalsIgnoreCase("mythical")){
// I know it is supposed to be Integer.parseInt(args[1]), but dont worry about that please.
if(args[1].equals("1") || args[1].equalsIgnoreCase("destroyer")){
player.giveItem(MythicalUtil.parseItem(new DestroyerItem()));
}else if(args[1].equalsIgnoreCase("shooter"){
plaer.giveItem(MythicalUtil.parseItem(new ShooterItem()));
}else if(...
}
I want to make a method that can return the item to me without spaghettifying my code.
If you really need to do all of that on Strings and Integers and you don't want to refactor all the code you already have but that particular part only, you can try to use switch case
String appropriateNameForArg0 = args[0].toUpperCase();
String appropriateNameForArg1 = args[1].toUpperCase();
if (appropriateNameForArg0.equals("MYTHICAL")) {
switch (appropriateNameForArg1) {
case "1":
case "DESTROYER":
player.giveItem(MythicalUtil.parseItem(new DestroyerItem()));
break;
case "SHOOTER":
plaer.giveItem(MythicalUtil.parseItem(new ShooterItem()));
break;
case "...":
// some other action here
default:
// here you have a place for actions which will be triggered if appropriateNameForArg1 will not meet any of the defined cases
break;
}
}

Use enum values for switch

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.

Java: returning a string from a method

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.

How do I access enum by int or by string

I have the following enum:
public enum Difficulty {
EASY(2), MEDUIM(3), HARD(5), EXTREME(8);
private int length;
Difficulty(int length) {
this.length = length;
}
public int length() {
return length;
}
}
I want to be able to reach the correct enum instance whether I know the number or the name.
For instance, if I have the int 3, I need a simple function that is able to return MEDIUM. And if I have the string extreme I need a simple function that is able to return 8.
By simple, I mean that I don't want to iterate each time or keep a static array inside the enum.
Answer must be in Java, Please. Thanks.
What edits do I need to make to the Difficulty enum structure?
public static Difficulty getByName(String name) {
return valueOf(name.toUpperCase());
}
public static Difficulty getByLength(int length) {
switch (length) {
case 2:
return EASY;
case 3:
return MEDIUM;
case 5:
return HARD;
case 8:
return EXTREME;
default:
throw new IllegalArgumentException("invalid length : " + length);
}
}

Is it possible to return more than one value from a method in Java? [duplicate]

This question already has answers here:
How to return multiple objects from a Java method?
(25 answers)
Closed 7 years ago.
I am using a simulator to play craps and I am trying to return two values from the same method (or rather I would like to).
When I wrote my return statement I simply tried putting "&" which compiled and runs properly; but I have no way of accessing the second returned value.
public static int crapsGame(){
int myPoint;
int gameStatus = rollagain;
int d1,d2;
int rolls=1;
d1 = rollDice();
d2 = rollDice();
switch ( d1+d2 ) {
case 7:
case 11:
gameStatus = win;
break;
case 2:
case 3:
case 12:
gameStatus = loss;
break;
default:
myPoint = d1+d2;
do {
d1=rollDice();
d2=rollDice();
rolls++;
if ( d1+d2 == myPoint )
gameStatus = win;
else if ( d1+d2 == 7 )
gameStatus = loss;
} while (gameStatus == rollagain);
} // end of switch
return gameStatus & rolls;
}
When I return the value as:
gameStatus=crapsGame();
It appropriately sets the varaible to win or lose but if I try something as simple as following that statement with:
rolls=crapsGame();
It is assigned the same value as gamestatus...a 0 or a 1 (win or lose).
Any way that I can access the second returned value? Or is there a completely different way to go about it?
Create your own value holder object to hold both values, then return it.
return new ValueHolder(gameStatus, rolls);
It's possible to return an array with multiple values, but that's cryptic and it does nothing for readability. It's much easier to understand what this means...
valueHolder.getGameStatus()
than what this means.
intArray[0]
returning gameStatus & rolls means "return the bitwise and of gameStatus and rolls" which probably is not what you want
you have some options here:
return an array
create a class that represents the response with a property for each value and return an instance
use one of the many java collections to return the values (probably lists or maps)
You can return an array of values or a Collection of values.
Is it possible to return more than one value from a method in Java?
No it is not. Java allows only one value to be returned. This restriction is hard-wired into the language.
However, there are a few approaches to deal with this restriction:
Write a light-weight "holder" class with fields for the multiple values you want to return, and create and return an instance of that class.
Return a Map containing the values. The problem with this (and the next) approach is that you are straying into an area that requires runtime type checking ... and that can lead to fragility.
Return an array containing the values. The array has to have a base type that will accommodate the types of all of the values.
If this is a method on an object, then add some fields on the same object and methods that allow the caller to pick up "auxiliary results" from the last call. (For example, the JDBC ResultSet class does this to allow a client to determine if the value just retrieved was a NULL.) The problem is that this makes the class non-reentrant at the instance level.
(You could even return extra results in statics, but it is a really bad idea. It makes the class non-reentrant across all instances, not to mention all of the other badnesses associated with misused statics.)
Of these, the first option is the cleanest. If you are worried about the overhead of creating holder instances, etc, you could consider reusing the instances; e.g. have the caller pass an existing "holder" to the called method into which the results should be placed.
The best practice for an OOP approach is to return an Object. An object that contains all the values you want.
Example:
class Main {
public static void main(String[] args) {
MyResponse response = requestResponse();
System.out.println( response.toString() );
}
private static MyResponse requestResponse() {
return new MyResponse( "this is first arg", "this is second arg" );
}
}
class MyResponse {
private String x, y;
public MyResponse( String x, String y ) {
this.x = x;
this.y = y;
}
#Override
public String toString() {
return "x: " + x + "\t y: " + y;
}
}
If you want an even more scalable approach then you have to use JSON responses. (let me know if you want an example with JSON too)
You can following ways to do this:
Use a Container class, for example
public class GameStatusAndRolls {
String gameStatus;
String rolls;
... // constructor and getter/setter
}
public static GameStatusAndRolls crapsGame(String gameStatus, String rolls) {
return new GameStatusAndRolls(gameStatus, rolls);
}
public static void main(String[] args) {
...
GameStatusAndRolls gameStatusAndRolls = crapsGame(gameStatus, rolls);
gameStatusAndRolls.getGameStatus();
Use List or an array, for example
public static List<Integer> crapsGame(String gameStatus, String rolls) {
return Arrays.asList(gameStatus, rolls);
}
private static final int GAME_STATUS = 0;
private static final int ROOLS = 0;
public static void main(String[] args) {
...
List<Integer> list = crapsGame(gameStatus, rolls);
... list.get(0)...list.get(GAME_STATUS);
... list.get(1)...list.get(ROOLS);
or
public static String[] crapsGame(String gameStatus, String rolls) {
return new String[] {gameStatus, rolls};
}
private static final int GAME_STATUS = 0;
private static final int ROOLS = 0;
public static void main(String[] args) {
...
String[] array = crapsGame(gameStatus, rolls);
... array[0]...array[GAME_STATUS];
... array[1]...array[ROOLS];
Use Map, for example
public static Map<String, String> crapsGame(String gameStatus, String rolls) {
Map<String, String> result = new HashMap<>(2);
result.put("gameStatus", gameStatus);
result.put("rolls", rolls);
return result;
}
public static void main(String[] args) {
...
Map map = crapsGame(gameStatus, rolls);
... map.get("gameStatus")...map.get("rolls");

Categories

Resources