I'm very new to enums and only have an elementary understanding of programming. I recently found out about enums and believe them to be the perfect solution to some of my problems but need some help on how to incorporate them into my code.
I started by creating an enum class. For now I'm working with 7 constants for my enum, and each constant has 1 String variable describing(?) it. How do i code this? And more importantly how do I access this from another class? For instance I want to print the string relating to the constant that is the current value of my enum. Please help. This was really hard for me to describe so hopefully you guys know what I'm trying to ask for.
This is already covered in the official tutorial
public enum Animal {
COW("moo"), // <== calls constructor with any enum specific data
HORSE("neigh"),
SHEEP("ba ba");
private final String noise; // stores the data
private Animal(String noise) { // <== private constuctor
this.noise = noise;
}
public String getNoise() { // <== allow access to the data
return noise;
}
}
Access from another class
Animal animal = Animal.COW;
System.out.println(animal.getNoise());
Enum constants override the toString method so by default it returns the constant name as a string. You can even override it further.
The Javadocs are your friend: http://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html#toString--.
You can also often use the enum constant itself directly.
public enum Rainbow {
RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET;
}
Used one way:
Rainbow rainbow = findRainbow();
switch (rainbow) {
case RED:
rosso();
break;
case YELLOW:
giallo();
break;
. . .
case VIOLET:
viola();
break;
}
etc.
Also, enums are classes and you can give them more methods, even override a method differently for each enum constant. Like Java already does with toString.
#shmosel already gave the link to the enum Tutorial.
To declare an enum, follow this synatx Colors("RED", "BLUE")
To access the enum class, declare it as a public class. If the class is in another package, import the class in to the class which is referencing those enums.
sorry my bad for saying to make it static
make it public . so that it can be accessed from any class that the class is imported to .
make somethingn like this from a different class
public class DifferentClass
{
public enum reportType
{
firstReport = 1,
secondReport = 2
}
}
import that class and access it like System.out.println("Report type : " + reportType.firstReport);
Related
So I've learned a bunch recently so I'm going back and sort of refactoring the homeworks from a previous course that I took to implement them using good practices. One homework had us implement a Planner object that contained an array of Course objects. I'm trying to create some Course constants so that I can access some popular Courses without having to create brand new Objects every time and so I can easily access them without going through the Course building process. I don't have much experience with enums and I can't seem to find anything on how I can actually use an Enum to store constants that are Objects. I originally wanted to make them constants in the Course class but Effective Java insists enumns should be used in such a situation. Does my implementation make sense at all? How should I go about making this enum that contains Course constants so I can actually retrieve them? I use the Builder method for creating a Course.
public enum Courses {
CSE_114, CSE_214, CSE_219, CSE_215;
private final static Course CSE_114_COURSE = new Course
.Builder("Computer Science 1", "Paul Fodor", 114)
.section((byte)1).department("CSE").build();
private static final Course CSE_214_COURSE = new Course
.Builder("Data Structures", "Ahmad Esmaili", 214)
.section((byte)1).department("CSE").build();
private static final Course CSE_219_COURSE = new Course
.Builder("Software Development", "Richard McKenna", 219)
.section((byte)1).department("CSE").build();
private static final Course CSE_215_COURSE = new Course
.Builder("Foundations of CS", "Paul Fodor", 215)
.section((byte)1).department("CSE").build();
public static Course get(Courses c) {
switch(c) {
case CSE_114: return CSE_114_COURSE;
case CSE_214: return CSE_214_COURSE;
case CSE_219: return CSE_219_COURSE;
case CSE_215: return CSE_215_COURSE;
default: throw new IllegalArgumentException("Course does not exist.");
}
}
}
You can actually treat an enum like an object:
public enum Course {
CSE_114("Computer Science 1", "Paul Fodor");
public final String room;
public final String lecturer;
private Course(room, lecturer) {
this.room = room;
this.lecturer = lecturer;
}
}
Because it is an enum, all values must be known at compile time. This is enforced by the Java language, which requires that the enum constructor is private.
While this would work for your situation, I don't recommend it - in fact, I don't recommend using an enum at all. An enum represents a fixed, known set of values. If you want to create more courses at runtime, then the enum is incomplete, and that contradicts the definition of an enum.
Instead, I suggest you use a CourseManager. Create one class, which holds the collection of all known courses. Then, when you need a course, you request it by name.
Course cs114 = courses.get("CS 114");
You could also take it one step further, by instantiating the CourseManager from a file, which contains a list of courses in a basic format like JSON.
That's not a bad implementation but I think a have a bit better solution: add an abstract method to your enum definition.
public enum Courses {
CSE_114 {
public Course getCourse() {
return CSE_114_COURSE;
}
}
...
private final static Course CSE_114_COURSE = new Course
.Builder("Computer Science 1", "Paul Fodor", 114)
.section((byte)1).department("CSE").build();
...
public abstract Course getCourse();
}
That way you can access to any course object vía Courses.CSE_114.getCourse() and you are also forcing that every enum has a course (imagine that you add an enum constant but forgot to add it in the get method. The way I proposed makes that scenario non sense)
You are mixing enum constants with static constants. Get these courses and selection of courses out of the enum class. Or you can use something like Andrew Williamson showed. Just don't mix the static constants with the enums. Static constants don't belong to the enum class. Enum class has a fixed set of values and that is where its role ends. All the other logic using these enums should be done somewhere else
One of the methods I am currently writing for my Java library takes an array of an arbitrary enumeration type as its sole argument. If any of these is non-null, I can access the instance of java.lang.Class representing that enumeration type, which may or may not be a public type. (If they are all null, there is no purpose to this anyway under the circumstances.) How do I get the number of possible values that enumeration type has? The approach I am currently using - Array.getLength(clazz.getMethod("values").invoke(null)); - fails when the Enum class is not public. How do I fix this?
The easiest way to get an array of enum constants from a Class object is
clazz.getEnumConstants();
To find the number of enum constants you can add .length to this.
If you want to get the array of enum constants from an instance of an enum, it is important to do
e.getDeclaringClass().getEnumConstants();
rather than
e.getClass().getEnumConstants();
The reason for this is demonstrated by the following example:
private enum Colour {
WHITE,
BLUE {
#Override
public String toString() {
return "blue";
}
}
}
public static void main(String[] args) throws Exception {
System.out.println(Arrays.toString(Colour.BLUE.getClass().getEnumConstants()));
System.out.println(Arrays.toString(Colour.WHITE.getClass().getEnumConstants()));
System.out.println(Arrays.toString(Colour.BLUE.getDeclaringClass().getEnumConstants()));
}
This program outputs
null
[WHITE, blue]
[WHITE, blue]
What is going on here is that in order to override the method toString for the BLUE constant, a subclass of Colour is created. This means that Colour.BLUE.getClass() does not return Colour.class, so Colour.BLUE.getClass().getEnumConstants() returns null. This issue does not apply for WHITE because WHITE does not require an extra class.
The first one is enum class
enum coffeeSize{
BIG(8), HUGE(10), OVERWHELMING(16);
private int ounces;
coffeeSize(int ounces ){
this.ounces = ounces;
}
public int getOunces(){
return ounces;
}
}
This is class CoffeeTest1 and main
public class CoffeeTest1 {
coffeeSize size;
public static void main (String args[]) {
CoffeeTest1 drink1 = new CoffeeTest1();
drink1.size = coffeeSize.BIG;
System.out.println(" " + drink1.size.getOunces());
}
}
The below is output
8
My question :
I don't understand the how drink1.size.getounces() manage to output 8. I haven't given constructor coffeeSize(8) object (ex: coffeeSize somex = new coffeeSize(BIG)). I want to know this simple subtle logic behind. Can someone help me understand please?
I dont understand the how "drink1.size.getounces() " manage to output 8.
[...]
I want to know this simple subtle logic behind.
To understand the logic behind this, you can think of your enum as a regular class (which is actually how it is compiled), and
BIG(8)
as an instance of this class similar to
new coffeesize(8);
It should now be clear why drink1.size.getOunces() prints 8: BIG is just an instance of the coffeesize enum, for which you set ounces to 8 when constructing it.
One suggestion: find, learn, and follow the Sun Java coding standards. It'll improve your code's readability.
It outputs 8 because that's the size, in ounces, for BIG coffee size, according to your enum. That's the value that you passed into the BIG constructor.
drink1 is the instance of the class, which has a package visible data member of type coffeeSize named size. Every coffeeSize instance has a method getOunces that returns the integer value that you passed into its constructor.
There's nothing subtle about it.
You will notice the getOunces method is defined on the enum. Enum values can themselves have properties and methods, in Java.
It is implied that CoffeeTest1 has a field that references the enum value.
So drink1 is an instance of that class..
the size property is set to the BIG instance of the enum..
Big has ounces 8.
When you specifies BIG(8) you are creating it passing 8 to its constructor (10 or 16). When you use it coffeeSize.BIG.getOunces() you are invoking its method getOunces. BIG, HUGE and OVERWHELMING are the possible values for a coffeeSize, each one with its own state.
enum Colour {
Black,White,Red,Green,Yellow,Grey
}
public class EnumExample {
public static void main(String[] args) {
Colour colour;
colour = Colour.Black;
System.out.println("Selected "+colour+" Colour");
colour = Colour.Yellow;
System.out.println("Selected "+colour+" Colour");
}
}
I have public enum like below:
public enum stringList1 {
string1,
string2,
string3,
string4,
string5,
}
This enum "stringList1" is referred in all over the code more than 100 places. Currently I have requirement to support below list as well.
enum stringList2 {
string1,
string2,
string6,
}
Actually code should pick either stringList1 or stringList2 depending on a condition.
I know enums can not be changed, also changing all over the code to put condition to pick right enum list is very difficult.
Here refactoring will not help, I need to pick either stringList1 or stringList2 at runtime, but currently stringList1 is referred all over the code. One option is putting the condition in all the places stringList1 is referred to pick stringList1 or stringList2, but this is very difficult.
UseCase: This is for backward compatibility, stringList1 for current version, say v2, stringList2 for v1. Data can be operated by V1 binary and V2 binary. Currenty if user tries to create data using V2 binary, it will create data, which is not understood by V1. So in version 2 binary I need to check, if version is 1, I need to used stringList2 else stringList 1
Lets say method method1(), which will create some predefined values with the help of stringList1, here user has access to method1() don't have access to enum values.
so user just simply call method1, I need to find the version, depending on the version, I have to use stringList1 or stringList2 but the problem is stringList1 is used all over the code :( as Classname.stringList1.values() or Classname.stringList1 in all over the code, for some internal processing
Please advise me how can I proceed in this case.
Thanks in Advance,
Ashok
maybe using the refactor function (from eclipse - i guess netbeans and others have something like that too) and renaming could help
public enum stringList {
stringList_string1,
stringList_string2,
stringList_string3,
stringList_string4,
stringList_string5,
}
public enum stringList2 {
stringList2_string1,
stringList2_string2,
stringList2_ string6,
}
hope this helps you :)
In your IDE you should be able to use refactoring to rename one instance and only rename just that instance (without change other enums)
If you need to keep the enums separate, i.e. not just add all the values together, you could make them implement an interface, e.g.
public interface stringListCommon {
}
public enum stringList implements stringListCommon {
..
}
public enum stringList2 implements stringListCommon {
..
}
This will allow you to pass these enums around with the same methods.
The better and modern way(I think you know enum is comming from C) is to structure special class for this operation. I will wrote you an example with playing card suits.
public class Suit {
private final String name;
private Suit(String name);
public static final Suit CLUBS = new Suit("clubs");
public static final Suit DIAMONDS = new Suit("diamonds");
public static final Suit HEARTS = new Suit("hearts");
public static final Suit SPADES = new Suit("spades");
/*other code is what you need you need(either final Suit[]
or final unmodifiableList to store values*/
class Creature {
private int yearOfBirth=10;
public void setYearOfBirth(int year) {
yearOfBirth = year;
}
void setYearOfBirth(Creature other) {
yearOfBirth = other.yearOfBirth; // is this correct it compiles fine
}
int getYearOfBirth() {
return yearOfBirth;
}
public static void main(String args[])
{
Creature c = new Creature();
c.setYearOfBirth(89);
Creature d = new Creature();
c.setYearOfBirth(d);
System.out.println(c.yearOfBirth);
}
}
Is there any mistake in this code?
Is "other.yearOfBirth" wrong? My faculty says it is wrong but it works fine for me.
As written, it will work, as you discovered. I suspect that there's a fundamental misunderstanding at play, though.
My psychic powers tell me that your instructor expected code more like the following:
class Creature {
private int yearOfBirth=10;
public void setYearOfBirth(int year) {
yearOfBirth = year;
}
public void setYearOfBirth(Creature other) {
yearOfBirth = other.yearOfBirth;
}
public int getYearOfBirth() {
return yearOfBirth;
}
}
class Program {
public static void main(String args[]) {
Creature c = new Creature();
c.setYearOfBirth(89);
Creature d = new Creature();
c.setYearOfBirth(d);
System.out.println(c.yearOfBirth); // This will not compile
}
}
The misunderstanding is that you've only created one class-- your main application class. This effectively makes yearOfBirth a sort of hybrid global value that you can access from your main method. In more typical designs, Creature is a class that is completely independent of your main method. In that case, you must only access Creature through its public interface. You would not be able to access its private field directly.
(Note to any pedants out there: Yes, I know I'm simplifying.)
You have to ask your faculty to explain why they think it's wrong (its perhaps a question of style, or even a misunderstanding), so you can learn from it.
Ultimately this person is going to impact your grades. This is an excellent opportunity to have a positive interaction with them. The more involved your teachers are with teaching you personally, the better your opportunity for mastering your subject will be.
If on the other hand when you're told something is wrong you go away privately and ask the general internet community, there is a risk that you'll be told you're right and you'll end up a false sense of superiority over your teachers which will be very counterproductive.
i detect nothing wrong.
the code works, because an instance or class can access private members of other instances of the same class. this is by design.
No, there is no problem at all with it.
Look, it depends on the viewer opinion. But for a given context this code may be just perfect.
For some other context this may not be correct. So it depends of how is going to be used.
Accessing a private member directly from another instance, is correct ( not always desirable though, for instance when you're subclassing ) that's why it is private in first place. You are saying "Hey, this is mine and I know how to use it"
Using the default access modifier for the other two methods, says that your intention is they should not be used by other classes outside the package.
Probably the only thing I would add is to make the class final.
final class Creature
If you want to make it inheritable you probably have to review the get/set for the yearOfBirth attribute, but they way it is is perfect to me.
NOW The most important thing here, is that you understand what each part of your code does, and how it affects its behavior.
You should no code just by luck ( sorry I don't know what's the correct expression for this ) but you should know what you're doing each time you type something, and how do you intend to be used.
I see two "issues," though I hesitate to call them mistakes:
You're explicitly setting Creature c's age as 89, and then rewriting that age with the uninitialized default (!) of Creature d. If this is what you intend to do, then fine, but at the very least you're wasting a few cycles to set a value that you intend to throw out later.
You're possibly violating the JavaBeans naming conventions.
To explain the latter point: a lot of Java libraries and frameworks (notably JSP) rely on JavaBeans to treat the object as a component. I haven't dived deeply into the actual mechanisms used, but from what I've read it relies on Introspection of the JavaBeans class to infer properties and the types of those properties. By overloading your setter setYearOfBirth() to accept both an int and a Creature, you could throw off the Introspection. (See here for a decent introduction to JavaBeans.)
This is not a big deal -- its entirely possible that you won't use this class as a JavaBean, and if you do it's trivial to refactor it so it works. But your teachers would probably prefer something a little cleaner, like the following:
class Creature {
private int yearOfBirth=10;
public void setYearOfBirth(int year) {
yearOfBirth = year;
}
int getYearOfBirth() {
return yearOfBirth;
}
public static void main(String args[])
{
Creature c = new Creature();
c.setYearOfBirth(89);
Creature d = new Creature();
c.setYearOfBirth(d.getYearOfBirth());
System.out.println(c.getYearOfBirth());
}
}
Now all of your access to yearOfBirth comes via the public getter methods, which helps encapsulation, and will prevent the code from breaking if your main method moves to another class. (As Greg D correctly pointed out.)
Also, this has the added benefit of making the intent of your code clear, which becomes more and more important when you start writing code for others to maintain and modify.
It's wrong because you're accessing a private member (you declared private int yearOfBirth) of another object although the class type is the same. You should use the public getter you defined instead: yearOfBirth = other.getYearOfBirth()
yearofBirth is a private int. Therefore the call to other.yearOfBirth would presumably fail...