I have recently learnt that Enums are kind of data types just like int, char etc. But in Enums we can define our on data types. But my question what is the necessity for user defined data types. I would be helpful if an example of real world scenario is provided.
An enum type is a special data type that enables for a variable to be
a set of predefined constants.
Here is some code that shows you how to use the Day enum defined above:
public class EnumTest {
Day day;
public EnumTest(Day day) {
this.day = day;
}
public void tellItLikeItIs() {
switch (day) {
case MONDAY:
System.out.println("Mondays are bad.");
break;
case FRIDAY:
System.out.println("Fridays are better.");
break;
case SATURDAY: case SUNDAY:
System.out.println("Weekends are best.");
break;
default:
System.out.println("Midweek days are so-so.");
break;
}
}
public static void main(String[] args) {
EnumTest firstDay = new EnumTest(Day.MONDAY);
firstDay.tellItLikeItIs();
EnumTest thirdDay = new EnumTest(Day.WEDNESDAY);
thirdDay.tellItLikeItIs();
EnumTest fifthDay = new EnumTest(Day.FRIDAY);
fifthDay.tellItLikeItIs();
EnumTest sixthDay = new EnumTest(Day.SATURDAY);
sixthDay.tellItLikeItIs();
EnumTest seventhDay = new EnumTest(Day.SUNDAY);
seventhDay.tellItLikeItIs();
}
}
The output is:
Mondays are bad.
Midweek days are so-so.
Fridays are better.
Weekends are best.
Weekends are best.
for more details check this tutorial.
User data types are like building blocks. We have the limited number of such standard blocks (e.g. primitive types), therefore, we need to expand them by building our own classes. Enum is a class with predefined values that cannot be changed.
For example,
public enum ProfessionType { DOCTOR, MANAGER, SELLER; }
We guarantee that it will create only one instance of DOCTOR, MANAGER and so on. Imagine, we are going to create a doctor type manually (in this case, ProfessionType is a class)
ProfessionType doctor1 = new ProfessionType("doctor");
ProfessionType doctor2 = new ProfessionType("doctor");
Which one is better? Am I a doctor of doctor1 type or of the second one?
Lets say we are asked to sum the position number of each alphabet of a sentence that was sent to a function
Example:
A=1,B=2,C=3....so on
so instead of using switch each char in loop and then add its value we could use Enum here , Because all values are incremented by 1 by default
public enum Alpha
{
A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z
}
// based on the input
public static int Count(string name="")
{
int sum = 0;
foreach (char item in name)
{
if (!string.IsNullOrWhiteSpace(item.ToString()))
sum += (int)Enum.Parse(typeof(Alpha), item.ToString().ToUpper());
}
return sum;
}
Related
I want to create a switch/case statement in Java and ensure that all the Strings are in the statement.
However, it is easy to create a enum in Java with simple Strings i.e. NORTH, SOUTH, EAST, WEST.
How would it be done for strings with dots and spaces? i.e. "This is the description", "com.stackoverflow.ClassName"
I think the main Problem of this question is, that your IDE is telling you that you are missing enum values within a switch statement. And asks you whether you would like to add them and not your compiler. This of course does not ensure a user of your enum class to have to use every value.
There is an approach mentioned by Joshua Bloch in his Effective Java book (Chapter Emulated extensible enum using an interface which can be changed to work with a switch shown here: Java Enum Switch. But I think the switch solution doesn't provide full security that all enums are used.
But since you wanted to know whether there is a solution using strings, we can also try using a functional approach as shown here: Enum Switch Functional Approach and make it work with string fields instead of enums.
This could look as follows:
public class Direction {
private static final String NORTH = "north";
private static final String SOUTH = "south";
private static final String EAST = "east";
private static final String WEST = "west";
public interface SwitchResult {
void NORTH();
void SOUTH();
void EAST();
void WEST();
}
public static void switchValue(String direction, SwitchResult result){
switch (direction){
case NORTH:
result.NORTH();
break;
case SOUTH:
result.SOUTH();
break;
case EAST:
result.EAST();
break;
case WEST:
result.WEST();
break;
}
}
public static void main(String[] args) {
String direction = "west";
Direction.switchValue(direction, new SwitchResult() {
#Override public void NORTH() {
System.out.println("this time north");
}
#Override public void SOUTH() {
System.out.println("this time south");
}
#Override public void EAST() {
System.out.println("this time east");
}
#Override public void WEST() {
System.out.println("this time west");
}
});
}
}
As you can see in the main method, if you want to call the switchValue function you have to pass your string and an implementation of your interface, which ensures you to override every possibility. In exchange for this the code is very redundant.
This approach could be used if you only have read access to a class which offers a bunch of String values and you want to build a switch statement around it. Anywhere else you should really stick to an approach using enums.
If you want to use third party tools to really ensure without having to write any redundant boilerplate code have a look at:
FindBugs SF_SWITCH_NO_DEFAULT: But this only covers default branch of switch statement.
#EnumMapper: Annotation processor which checks at compile-time that all enum constants are handled
If you are asking whether you can create an enum where the constants have spaces, then the answer is 'no'.
Enum constants are normal Java identifiers, like class or variable names so they can not have spaces or special characters in them.
However is it impossible to link an enum with a String? No.
If for some reason you want your switch case to use an enum for readability/brevity, but your inputs are Strings that can have spaces, dots, special characters..., then there is a way.
You need to extend your enum to have an extra field (let's call it label) to hold this String.
In your method with the switch case that uses the enum, you can call a findByLabel method
that returns the enum that corresponds to the provided String.
Here is a little example class that uses your enum values NORTH, EAST, SOUTH, WEST,
linked to Strings of different (invalid enum naming) structures.
public class EnumExample {
enum SwitchEnum {
NORTH ("North star"),
EAST ("Eastpack rulez!"),
SOUTH ("https://www.southafrica.net/"),
WEST ("java.awt.BorderLayout.WEST");
private final String label;
SwitchEnum(final String label) {
this.label = label;
}
#Override
public String toString() {
return this.label;
}
private static final Map<String,SwitchEnum> map;
static {
map = new HashMap<String,SwitchEnum>();
for (SwitchEnum v : SwitchEnum.values()) {
map.put(v.label, v);
}
}
public static SwitchEnum findByLabel(String label) {
return map.get(label);
}
}
public static String doEnumSwitch(String enumString) {
SwitchEnum enm = SwitchEnum.findByLabel(enumString);
if (enm != null) {
String enumReturn = enm.name() +" : "+ enm;
switch (enm) {
case NORTH:
return enumReturn +" - Up there.";
case EAST:
return enumReturn +" - Now for sale.";
case SOUTH:
return enumReturn +" - Now with 50% more elephants.";
default:
return "UNHANDLED ENUM : "+ enm.name() +" - "+ enm;
}
} else {
return "UNKNOWN ENUM : "+ enumString;
}
}
public static void main(String[] args) {
System.out.println(doEnumSwitch("North star"));
System.out.println(doEnumSwitch("Eastpack rulez!"));
System.out.println(doEnumSwitch("https://www.southafrica.net/"));
System.out.println(doEnumSwitch("java.awt.BorderLayout.WEST"));
System.out.println(doEnumSwitch("I only want to get out of here."));
}
}
This outputs the following
NORTH : North star - Up there.
EAST : Eastpack rulez! - Now for sale.
SOUTH : https://www.southafrica.net/ - Now with 50% more elephants.
UNHANDLED ENUM : WEST - java.awt.BorderLayout.WEST
UNKNOWN ENUM : I only want to get out of here.
I coded myself an issue last night while developing a small game. The other day, I convinced myself that I should devote some of my spare time to something productive, so instead of gaming I decided I would start working on a text-based rpg. I came, then, to the issue of representing currency in game. Now, because this is just for fun, I'd like to challenge myself a bit. Instead of just representing currency as a single value ( eg: a single type of coin called "gold piece" isn't the only kind of coin in the game .)
What I decided to do was create 4 types of coin - pence, copper, denar, and oren. All 4 of the coins have values such as weight, volume, material, and name. Furthermore, the coins have exchange rates, which determine their relative values. The point of this was to permit different usages of what would otherwise be a boring old currency. My issue is that I am unsure how to implement it.
What I arrived at last night was 4 classes ( Pence, Copper, Denar, Oren, ) extending an abstract class Coin. Coin contains a lot of protected static elements, such as DENSITY, VOLUME, NAME, EXCHANGE for all 4 subclasses.
The constructors for the sub-classes look like this:
public Coppers() {
super();
super.metal = COPPER_METAL;
super.name = COPPER;
super.setVolume();
super.setDensity();
super.setWeight();
}
And the methods in the super class look like this:
protected void setDensity() {
switch( getMetal()) {
case "copper":
this.density = DENSITY_COPPER;
break;
case "silver":
this.density = DENSITY_SILVER;
break;
case "gold":
this.density = DENSITY_GOLD;
break;
default:
this.density = DENSITY_COPPER;
break;
};
}
This seems terribly... wrong. I'm not sure what the best practice would be. I asked my friends about using a static class to hold these values, and received mixed responses. The POINT of these classes though, is important. Imagine the player class has an object called Purse, which keeps track of the number of different types of coins. With their Purse, the player can exchange coins at banks, purchase goods, and sell goods for coins. It wouldn't make any sense to hold a Set of all instantiated coins, right? I just need the information, and the methods. Does implementing a static class make sense, then? How can I get all 4 coins working best, when they all share so many properties?
What you may do in this case is to use an Enum. You enumerate the constants you need, give them a type through their constructors.
Now that we have their type, we can compare it to the string you're handling within your code, if none of the types match, we set it to Density.COPPER by default.
Density density;
protected void setDensity (String metal) {
for (Density d : Density.values()) {
if (metal.equals(d.getType())) {
this.density = d;
return;
}
}
this.density = Density.COPPER;
}
enum Density {
COPPER("copper"),
SILVER("silver"),
GOLD("gold");
String type;
Density(String s) {
type = s;
}
public String getType() {
return type;
}
}
Let's work backwards here.
Imagine the player class has an object called Purse, which keeps track of the number of different types of coins. With their Purse, the player can exchange coins at banks, purchase goods, and sell goods for coins.
What this implies:
public class Purse {
private final List<Coin> coins = new ArrayList<>();
}
This tells me that enums are not sufficient (enough) here. An enum in this context describes multiple states; what you're looking for are actual objects which can hold values that you need to do some calculations on.
If our intention is to hold on to this currency, I don't see anything wrong with some central object to describe it.
In my mind, using an abstract class for this is probably fine, but you're missing a critical component: a factory to create the type of coin you want. You'll also want to reduce the responsibilities of the coin altogether - it's fine for a coin to know its value, but it shouldn't care what its value is relative to other coins; that's the responsibility of some kind of exchange object which intends to produce a number of coins based on the value of your given coin.
So let's write the constructor for the abstract class. If we're thinking of creating a generic coin, we need to know its volume, density, and weight. The name is provided by virtue of its class name, so you really shouldn't need to worry about that; you can extract it later.
If you want some sort of coin hierarchy, you can leverage Comparable; state the ordering there instead of through enumeration.
public abstract class Coin implements Comparable<Coin> {
protected final int volume;
protected final int density;
protected final int weight;
public Coin(int volume, int density, int weight) {
this.volume = volume;
this.density = density;
this.weight = weight;
}
public int getVolume() {
return volume;
}
public int getDensity() {
return density;
}
public int getWeight() {
return weight;
}
}
This describes the barebones Coin type.
For an example, let's describe the Copper type here as well. This code makes the assumption that coin of the same type is comparable otherwise it demotes itself (with Copper being at the bottom of the list).
Observe a few things:
We preserve a lot of the original logic from the parent class
We override compareTo (because we must), and we let that drive the chief way of ordering on coins.
This does not describe any sort of conversion since the coins really shouldn't need to know about that. They have no value between coins until it's time to actually convert them. Think foreign exchange.
public class Copper extends Coin {
public Copper(final int volume, final int density, final int weight) {
super(volume, density, weight);
}
#Override
public int compareTo(final Coin otherCoin) {
if(otherCoin instanceof Copper) {
return (volume - getVolume()) + (density - getDensity()) + (weight - getWeight());
}
// assume Coppers are worth the least
return Integer.MIN_VALUE;
}
}
The other currencies are left as an exercise for the reader.
The last thing I want to cover is some form of generator for all of your currencies. This is where a bit of reflection magic can really help to invoke the constructor you care about.
I've also made this return an Optional<T extends Coin> so that, in the event the generation fails for some reason, you have an optional to work with instead of null.
public class CoinFactory {
private CoinFactory() {
}
public static <T extends Coin> Optional<T> generateCoin(int weight, int volume, int density, Class<T> clazz) {
Optional<T> coin = Optional.empty();
try {
coin = Optional.of(clazz.getDeclaredConstructor(int.class, int.class, int.class)
.newInstance(weight, volume, density));
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
return coin;
}
}
You can use this main method to smoke test it:
public static void main(String[] args) {
final Optional<Copper> x = CoinFactory.generateCoin(10, 20, 30, Copper.class);
if(x.isPresent()) {
System.out.println(x.get());
}
}
Put a private Map in Coin for Density, with keys being "copper", "gold", and "silver", and the values being the DENSITY_ constants. setDensity() should simply run:
this.density = densityMap.get(getMetal());
Or better yet, scrap setDensity(), and instead simply have getDensity(), which returns densityMap.get(getMetal()).
Since the four kinds of coin don’t differ in behavior, one class is enough. I suggest this:
public enum Coin {
PENCE, COPPER, DENAR, OREN;
private static final String[] METAL = { "copper", "copper", "silver", "gold" };
private static final int[] VALUE = { 1, 12, 60, 360 };
public String getMetal() {
return METAL[ordinal()];
}
public int getValue() {
return VALUE[ordinal()];
}
}
I wrote a library
This library accept the limited options and print the related string.
public class Lib {
public enum Num {
ZERO,
ONE,
TWO,
THREE
}
public static void main(String[] args) {
Lib obj = new Lib();
obj.print(Num.ONE);
}
public void print(Num num) {
switch (num) {
case ZERO:
System.out.println("ZERO is "+Num.ZERO.ordinal());
break;
case ONE:
System.out.println("ONE is "+Num.ONE.ordinal());
break;
case TWO:
System.out.println("TWO is "+Num.TWO.ordinal());
break;
case THREE:
System.out.println("THREE is "+Num.THREE.ordinal());
break;
default:
break;
}
}
}
In the new version, I will disable option ONE and TWO
public enum Num {
ZERO,
//ONE,
//TWO,
THREE
}
How can I keep the correct values after I disabled the options?
It is not clear what you are asking. If you change any piece of code and thereby "remove" "names" that formerly existed ... than of course, any "reference" to any of the deleted elements is ... first of all: broken.
In case of an enum, you might prefer to not rely on build-in ordinals; instead you could go for this:
enum Whatever {
ONE(1), TWO(2);
private final int value;
private Whatever(value) {
this.value = value;
}
public int getValue() { return value }
But you have to be really careful here. For example, if you are persisting enum objects (into some sort of database for example) then any such change (adding or removing enum "values") will lead to incompatibilities!
I am not sure of what you want to do, but for example you can do this:
public enum Num {
ZERO,
ONE,
TWO,
THREE
}
switch (num) {
case ZERO:
System.out.println("ZERO is "+Num.ZERO.ordinal());
break;
case THREE:
System.out.println("ZERO is "+Num.THREE.ordinal());
break;
case One:
case Two:
default:
break;
You might be disable some of enum now onward and keep stored as it is. To support both the things, you should have a method that returns list of enum that will populate on UI. I.E. List getPopulatedOnUi(). That contains those enum list that you needed.
Don't remove from definition itself. keep as it is. because that will throw error for existing as it might be stored into database.
You can modify the print() method as below: Instead of switch, you can use for loop and make the code little bit generic. Now, even when your enum values changes, you need not to make any changes in this code.
It will handle the case , If you disable some enum values in future.
public void print(Num num) {
for(Num n : Num.values()) {
if(n == num) {
System.out.println(n.name()+ " is " + n.ordinal());
break;
}
}
}
Is it possible to use an enumeration in the following circumstance:
Let’s say you have a certain amount of predefined 'read types'. Example read types could be: Diagnostic, KWH, MaxDemand, OnPeak, etc. And for each of these read types, there’s a ‘TIMTagNumber’ which is essientally a protocol for retrieving each predefined read type.
For example, TIMTagNumber 1100 would retrieve the read type Diagnostic
TIMTagNumber 1300 would retrieve the read type KWH.
The problem is that a predefined read type can sometimes be retrieved by more than one TIMTagNumber.
I want to create an enumeration ReadType that would define each read type and all TIMTagNumbers that can be used to retrieve that read.
Can you use an enumeration in this way?
public enum ReadType{
KWH(1300)
Diagnostic(1100)
ReadType3(1400, 1401) // This read can be retrieved by both 1400 and 1401
}
If an enumeration is not the way to go, is there an elegant or efficient way to define these read types? The overall desired outcome of all this essientally is being recognizing what type of read it is based on the TIMTagNumbers.
I.E. Given 1400 OR 1401 you would know that it's 'ReadType3'.
Can you do this? Yes. Whether it's the right decision will depend on whether you want to couple these TIMTagNumbers to the read type. If not, a simple Map<Integer, ReadType> will probably suffice.
Here's how you could do it:
public static enum MyEnum {
KWH(1300),
Diagnostic(1100),
ReadType3(1400, 1401);
private Set<Integer> timTagNumbers;
MyEnum(Integer... timTagNumbers) {
this.timTagNumbers = new HashSet<Integer>(Arrays.asList(timTagNumbers));
//add check to make sure that values are unique across all instances
}
public static MyEnum forTIMTagNumber(int num) {
for ( MyEnum readType : values() ) {
if ( readType.timTagNumbers.contains(num) ) {
return readType;
}
}
throw new NoSuchElementException("No ReadType matching TIMTagNumber " + num);
}
}
//...
int timTagNumber = 1400;
ReadType readType = ReadType.forTIMTagNumber(timTagNumber);
As I said above, this style works well when the data and the enum types are intrinsically coupled already. It would not be good for when the enum type is decoupled from the mapped values (e.g. the values are used for one of many ways of serializing the enum) or if the values are configuration-specific or even dynamic (e.g. if they were prices on an item). In these cases it is usually best to externalize this mapping in an EnumMap or Map.
public enum ReadType {
KWH(1300),
Diagnostic(1100),
ReadType3(1400, 1401);
private int[] timTagNumbers;
private ReadType(int ... numbers) {
this.timTagNumbers = numbers;
}
public int[] getTimTagNumbers() {
return timTagNumbers;
}
public static ReadType forTimTagNumber(int n) {
for (ReadType type : values()) {
if (Arrays.binarySearch(type.timTagNumbers, n) != -1) {
return type;
}
}
throw new NoSucheElementException(); // if not found
}
With this you can do
int[] timTagNumbers = ReadType.Diagnostic.getTimTagNumbers(); // [ 1100 ]
and
ReadType type3 = ReadType.forTimTagNumber(1401); // ReadType.ReadType3
You can indeed use enumerations in that way, but your example is missing a private field and a constructor.
Something like:
public enum Bla{
CASE1(100),CASE2(200);
private int amount;
private Bla(int amount) {
this.amount = amount;
}
public Bla getByValue(int value){
switch (value) {
case 100: return CASE1;
case 200: return CASE2;
}
return null;
}
}
I've included a "reverse lookup" method that returns an Enum given the value.
The main advantage is that you can have the rest of your code using "Bla" instead of int's which will guarantee type-safety on your operations, basically, it'll make impossible to pass an invalid int value as a method parameter (and you can use switch statements over enums too, and that's pretty awesome in some usage scenarios).
EDIT: I noticed after I posted that you need more then one int to specify the Enum, but the same logic applies, with the due changes in the methods, of course.
You could do something like the following, when you supply values in the parentheses where the enum variable is declared, it is calling the constructor of the enum. You need to create a different method in the enum itself to get the enum type from the integer value. See below.
public enum ReadType {
KWH(), DIAGNOSTIC(), READTYPE3();
public ReadType getReadType(int num) {
ReadType toReturn = KWH;
switch (num) {
case 1300:
toReturn = KWH;
break;
case 1100:
toReturn = DIAGNOSTIC;
break;
case 1400:
toReturn = READTYPE3;
break;
case 1401:
toReturn = READTYPE3;
break;
}
return toReturn;
}
If you can impose some restrictions like no more than 2 tags can be associated with a read type and each tag is no greater than 2^15, then you can store the two numbers into 1 integer. See this S/O post for more details.
I have some enums like this:
public enum Classification {
UNKNOWN("Unknown"),
DELETION("Deletion"),
DUPLICATION("Duplication"), ....
but some of them have like 20 members, so currently in code I deal with them with huge if/else blocks like this:
int classification= rs.getInt("classification");
if (classification == Classification.UNKNOWN.ordinal()) {
variant.setClassification(Classification.UNKNOWN);
} else if (classification == Classification.DELETION.ordinal()) {
variant.setClassification(Classification.DELETION);
( rs is from JDBC tho).
Does Java have a better way this these big if/else blocks to do what I am doing? some sorting of looping through it?
You could use Enum#values() to get all enum values in an array. The ordinal maps 1:1 to the array index. Add the following method fo your Classification enum:
public static Classification of(int ordinal) {
if (0 <= ordinal && ordinal < values().length) {
return values()[ordinal];
}
throw new IllegalArgumentException("Invalid ordinal " + ordinal);
}
and use it as follows
Classification classification = Classification.of(rs.getInt("classification"));
// ...
However, using enum's ordinal for this is not the best practice. What if some developer rearranges the enum's values or adds/removes values? Even the javadoc warns that it has usually no use for developers. Rather give each enum value a fixed identifier. You could pass it in as an additional argument of the enum constructor argument. You could even use enum's String representation for that.
UNKNOWN(1, "Unknown"),
DELETION(2, "Deletion"),
DUPLICATION(3, "Duplication"),
// ...
Then use that value for DB instead and modify the of() method to walk through them in a foreach loop:
public static Classification of(int id) {
for (Classification classification : values()) {
if (classification.id == id) {
return classification;
}
}
throw new IllegalArgumentException("Invalid id " + id);
}
If the db value is the ordinal of the Enum then:
int classification= rs.getInt("classification");
variant.setClassification(Classification.values()[classification]);
I'll leave bounds checking as an exercise for the reader.
You can loop through an enumeration’s values via the object the someEnum.values() method returns:
for (Classification clz : Classification.values()) doSomethingWith(clz);
found here
I don’t know how exactly I can help you, since i don’t know what rs.getInt(String) does.
It seems to give back an Integer representing a enum value of Classification, but why?
Use variant.setClassification(YourEnumClassHere.values()[classification]). Enum.values() returns an array of all the declared enums in that class.
Instead of storing ordinal, you can store the name and use the valueOf method to convert the String back to your Enum type.
If you willing and able to store a string representation (this is a good technique) of the ENUM in your database, see Reference from Gareth Davis in comments above. If you are unwilling and/or unable to store a string representation and must continue with an ordinal representation, I suggest that a Map is called for. Here is some example code:
public class EnumMap
{
private enum FistSounds
{
Blam, Kapow, Zowie, Biff;
private static Map<Integer, FistSounds> ordinalMap = new HashMap<Integer, FistSounds>();
static
{
ordinalMap.put(Blam.ordinal(), Blam);
ordinalMap.put(Kapow.ordinal(), Kapow);
ordinalMap.put(Zowie.ordinal(), Zowie);
ordinalMap.put(Biff.ordinal(), Biff);
}
public static final FistSounds getByOrdinal(final int enumIndex)
{
return ordinalMap.get(enumIndex);
}
}
public static void main(String[] args)
{
FistSounds fistSound;
for (int index = -1; index < 5; ++index)
{
fistSound = FistSounds.getByOrdinal(index);
System.out.print("Ordinal: ");
System.out.print(index);
System.out.print(", FistSound: ");
System.out.println(fistSound);
}
}
}
I'd recommend using a switch statement, if the logic to execute is different for each case....
do as #Gareth Davis instructs and then just have a switch statement and handle each case as required.
Enums are also eligible to be used in switch statements see here