enum icecream {
vanilla(100), strawberry(20);
int price;
icecream(int i) {
price = i;
}
}
I am a little confused as to how the enum objects are created during compilation time
I saw some examples where they mentioned it like this
public enum Flavor
{
COFFEE, VANILLA, CHOCOLATE, STRAWBERRY, RUM_RAISIN, PEACH
}
This gets translated into(during compilation)
public final class Flavor
extends java.lang.Enum
{
public static final Flavor COFFEE = new Flavor("COFFEE", 0);
public static final Flavor VANILLA = new Flavor("VANILLA", 1);
// ...
}
Link: http://www.kdgregory.com/index.php?page=java.enum
But how are the objects created when I pass a value along with the name cause to me they just look like method calls. E.x. vanilla(100) here for vanilla the price is 100 but how does it actually gets created? I am not getting it at all. Please help :(
the vanilla(100), strawberry(20) is just a java5+ notation. It gets translated during the compilation to proper object creation code:
public static final icecream vanilla = new icecream(100);
public static final icecream strawberry = new icecream(20);
BTW, java type should be CamelCased, so, icecream should be named IceCream.
Enums are read by the java compiler as constants, but ultimately, they are implemented like any other objects (that is, they are not special types, like ints/floats/arrays, but rather, a syntactic wrapper over a pure object-oriented language feature). Thus, enums have constructors which you can override, so that your static enums have more than just a name. This can be very useful, for example, if you want your enumerated values to have multiple fields.
For example, I may have an Animal enum, where each animal has a name, as well as a number of legs :
public enum Animal{
Dog(4), Baboon(2);
public int legs;
private Animal(int legs) {
legs=legs;
}
}
However, in the absence of such overriding, the compiler generate default enumeration objects, which is essentially what you have pasted.
Related
Assume I want to define types that are similar in structure, but differ in a parameter that could be an integer or could be something else.
Is it possible in Java to define a family of classes parameterized by an integer or even an arbitrary object?
Consider the following pseudocode (which does not compile):
/**
* String of a certain length n and a method to reduce to length n-1
*/
public class StringN<int n> {
private String str;
public StringN( String str) {
if(str.length() != n) {
throw new IllegalArgumentException("string is not of required length!");
}
this.str = str;
}
public StringN<n-1> reduce() {
return new StringN<n-1>(s.substring(0, s.length() - 1));
}
#Override
public String toString() {
return str;
}
}
Other even more natural examples that come to my mind are tensor-products in math, so where to put the parameter 'n', if one wants to define e.g. the space R^n as a Java class or in functional programming the 'arity' of a Function<>-space. So how to define a family of classes with different arity, parameterized by n?
If this is not possible in Java, does this concept exist in other more functional languages and what is the proper name for it? (like maybe 'parameterized class'?)
Edit: as a reaction to comments, the last part was just to know the general name of such a concept, not to make a detour to other languages.
Alas, Java requires type parameters to be types (actually, it even requires them to be reference types), and since all integers are of the same type, you not get the compiler to distinguish generics depending on the value of an integer.
The usual workaround is to declare a separate type for each possible (or needed) value. To share structure, you can use an abstract base class. And if the base class needs any concrete types, the subclasses can pass them as type parameters:
abstract class StringN<S extends StringN<S,P>, P extends StringN<P,?>>
implements Comparable<S> {
final String value;
protected StringN(String value, int n) {
if (value.length() != n) {
throw new IllegalArgumentException(value);
}
this.value = value;
}
#Override
public int compareTo(S o) {
return value.compareTo(o.value);
}
abstract P newP(String value);
public P removeLast() {
return newP(value.substring(0, value.length() - 1));
}
}
class String0 extends StringN<String0, String0> {
protected String0(String value) {
super(value, 0);
}
#Override
String0 newP(String value) {
throw new UnsupportedOperationException();
}
}
class String1 extends StringN<String1, String0> {
protected String1(String value) {
super(value, 1);
}
#Override
String0 newP(String value) {
return new String0(value);
}
}
class String2 extends StringN<String2, String1> {
protected String2(String value) {
super(value, 2);
}
#Override
String1 newP(String value) {
return new String1(value);
}
}
public class Test {
public static void main(String[] args) {
String2 s2 = new String2("hi");
String1 s1 = s2.removeLast();
s1.compareTo(s2); // compilation error: The method compareTo(String1) is not applicable for the arguments (String2)
}
}
As you can see, as long as the set of values is finite and known up front, you can even teach the compiler to count :-)
However, it gets rather unwieldy and hard to understand, which is why such workarounds are rarely used.
Yours is an interesting question, but I think you went too far in assuming that the solution to your need is necessarily a parametrized class.
Parametrized classes are composition of data types, not values.
Since you do not require the compile to enforce any additional static type checkings on your code, I think a programmatic solution would be enough:
First step: Move your pseudo-parameter "int n" to a final variable:
public class StringN {
private final int n;
private String str;
public StringN( String str) {
if(str.length() != n) {
throw new IllegalArgumentException("string is not of required length!");
}
this.str = str;
}
public StringN reduce() {
return new StringN(s.substring(0, s.length() - 1));
}
#Override
public String toString() {
return str;
}
}
Of course, this do not compile yet. You must initialize the n variable on every constructor (declarations and callings).
If you feel uncomfortable with the fact of exposing the parameter n as part of the public constructors calling, that can be solved restricting the constructors to package access, and bringing the construction responsibility to a new Factory class, which must be the only public way to create StringN objects.
public StringNFactory
{
private final int n;
public StringNFactory(int n)
{
this.n=n;
}
public StringN create(String s)
{
return new StringN(this.n, s);
}
}
As the name suggests, a "type parameter" is a type. Not 'a length of a string'.
To be specific: One can imagine the concept of the type fixed length string, and one can imagine this concept has a parameter, whose type is int; one could have FixedString<5> myID = "HELLO"; and that would compile, but FixedString<5> myID = "GOODBYE"; would be an error, hopefully a compile-time one.
Java does not support this concept whatsoever. If that's what you're looking for, hack it together; you can of course make this work with code, but it means all the errors and checking occurs at runtime, nothing special would occur at compile time.
Instead, generics are to give types the ability to parameterize themselves, but only with a type. If you want to convey the notion of 'A List... but not just any list, nono, a list that stores Strings' - you can do that, that's what generics are for. That concept applies only to types and not to anything else though (such as lengths).
Furthermore, javac will be taking care of applying the parameter. So you can't hack it together by making some faux hierarchy such as:
public interface ListSize {}
public interface ListIsSizeOne implements ListSize {}
public interface ListIsSizeTwo implements ListSize {}
public interface ListIsSizeThree implements ListSize {}
and then having a FixedSizeList<T extends ListSize> so that someone can declare: FixedSizeList<ListIsSizeTwo> list = List.of(a, b);.
The reason that can't work is: You can't tell javac what to do, it's not a pluggable system. Java 'knows' how to apply type bounds. It wouldn't know how to enforce size limits, so you can't do this.
I'm answering the question myself, because the useful information is distributed over several comments/answers. I made this a community-wiki answer, so that I don't earn reputation for suggestions of others.
The feature I'm looking for is apparently a particular case of so-called dependent-typing (thanks #DylanSp). Also template parameters of C++ (with the parameter not being a type) are an example of such a feature (thanks #Turing85). All answers agree that this feature unfortunately does not exist in Java, neither within the syntax of Java Generics (#rzwitserloot and others pointed out that Java specification allows only reference types in the diamond <>), nor any other syntax.
One certainly can manually define types in Java for each particular n. So for my example in my question, one can define classes String1, String2, String3, ..., but only finitely many ones. In order to make the definition of each particular type as simple as possible, one can use an approach with an abstract base class that is shared by all of these classes, see #meriton's nice suggestion.
Not what I was thinking of, but with finitely many cases also a code generator (mentioned by #Hulk) should be an option. If I understand correctly that's also what #MC Emperor had in mind when mentioning annotations.
However, if one really wants to stick to infinitely many classes (that's what I want), the only way out seems to be, to make the counter n a member of a single class and just think of them being different types. At compiler-level, there won't be any type-checking, so one has to implement type-safety oneself. The suggestion with the factory made by #Little Santi would be a way to bring more structure into this approach.
I have the following problem and wonder whether there is an efficient solution to it.
(I am using Java)
Imagine you have multiple different types of classes holding the same data in variables with different name and consider this given.
Here an example:
Imagine there are the three empiric values as member within a container class
short color
int size
String shape
and consider the two classes
class1
class2
class1 has three member variables being the empiric values:
short rgb_color -> corresponds to color
long bigness -> corresponds to bigness
String contour -> corresponds to shape
class2 has three member variables being the empiric values:
int cmyk -> corresponds to color
int greatness -> corresponds to bigness
String shapecountour -> corresponds to shape
As you see the names are different. So if I want to import the values from class one and two into the container class, I would need to
convert every parameter by itself in order to add it to the container class and thus
I need to type as there are member variables (here 6)
e.g. see this pseudo code for the import function:
public void import(class1 class){
this.color = (short) class.rgb_color;
this.size = (int) class.bigness;
this.shape = (String) class.contour;
}
public void import(class2 class){
this.color = (short) class.cmyk;
this.size = (int) class.greatness;
this.shape = (String) class.shapecontour;
}
Now imagine problems, where there are much more parameters.
Is there a generic way to solve the import as to do it one by one for each member?
Thank you for your help.
EDIT: Thanks already for the fast answers.
As I said I cannot modify class1 and class2.
I have checked the reflection, where they have this example for changing the fields.
public class Book {
public long chapters = 0;
public String[] characters = { "Alice", "White Rabbit" };
public Tweedle twin = Tweedle.DEE;
public static void main(String... args) {
Book book = new Book();
String fmt = "%6S: %-12s = %s%n";
try {
Class<?> c = book.getClass();
Field chap = c.getDeclaredField("chapters");
out.format(fmt, "before", "chapters", book.chapters);
chap.setLong(book, 12);
out.format(fmt, "after", "chapters", chap.getLong(book));
Field chars = c.getDeclaredField("characters");
out.format(fmt, "before", "characters",
Arrays.asList(book.characters));
String[] newChars = { "Queen", "King" };
chars.set(book, newChars);
out.format(fmt, "after", "characters",
Arrays.asList(book.characters));
Field t = c.getDeclaredField("twin");
out.format(fmt, "before", "twin", book.twin);
t.set(book, Tweedle.DUM);
out.format(fmt, "after", "twin", t.get(book));
// production code should handle these exceptions more gracefully
} catch (NoSuchFieldException x) {
x.printStackTrace();
} catch (IllegalAccessException x) {
x.printStackTrace();
}
}
}
But still I need to call each variable by name as e.g. "chapters".
What do I get wrong?
You have two options to resolve the issue:
To change the design, as suggested above. It seems that inheritance of some base class (with these three fields) should work fine.
If you don't have a way to modify these two classes (class1, class2) => You have to specify the mapping between the fields anyway. The straightforward way is your option with converters. Other option is to define the mapping with annotations/xml/etc. and to use some mapping tool. These conversation has a good list of them:
any tool for java object to object mapping?
Dozer seems to be the most promising for me.
You can use java reflection api to obtain list of available fields and than match them by type.
Why don't you do this change your design a bit : Create a parent class and pull those parameters in to parent class, and let your Class1,Class2 extend new Parent class. Now access those parameters.
class BaseClass{
short color;
int size;
String shape;
}
class Class1 extends BaseClass{
-----Other Class Properties----------
}
class Class2 extends BaseClass{
-----Other Class Properties----------
}
Are there any objects created respective to each of the enum constants ARROGANT, RASCAL, IDIOT?
public enum Manager {
ARROGANT,
RASCAL,
IDIOT
}
and if the following code does the same as the above, explicitly though,
public enum Manager {
ARROGANT(),
RASCAL(),
IDIOT();
Manager() {}
}
Yes, exactly one instance will be created for each enum constant.
And yes, the second sample code is effectively identical.
Yes, both should result in the same bytecode, the first is only syntactic sugar.
The second is useful when you have to associate values with an enum.
enum Numbers{
ONE(1),TWO(2),THREE(3),TEN(10);
Numbers(int i){
value = i;
}
public final int value;
}
I am doing astrophysical research. I wrote a package containing the classes Star, Band, and Datfile. I also have the enumerated type of BandName. Each star contains several Bands, each Band contains several Datfiles.
I have observational data for several galaxies. For each of these, I make a StarDatabase class (a HashMap of Stars) and a Main class.
The problem I'm having is with the enumerated type of BandName. So far, all of the data I have used has been in the I and V bands. Now I have data in J, H, and K bands. If I simply add J, H, and K to BandName, all of my loops that iterate over all of the items in BandName and do something are now broken.
Any ideas?
Edit: To sum up my problem, I want every package to have its own BandName enum that it can iterate through. But this doesn't work, because the methods in the Star package are expecting objects of type Star.BandName and I am providing objects of type IndividualPackage.BandName.
You can't inherit an enum from another enum, although you can have your enum implement an interface. The technical problem (that all enums implicitly extend java.lang.Enum, thus they can't extend another class, only implement additional interfaces) is no accident:
For the most part, extensibility of enums turns out to
be a bad idea. It is confusing that elements of an extension type are instances of
the base type and not vice versa. There is no good way to enumerate over all of the
elements of a base type and its extension. Finally, extensibility would complicate
many aspects of the design and implementation.
From Effective Java 2nd Edition, Item 34.
However, I don't fully understand your problem: haven't you used values() for iterating through your enum? Then you shouldn't worry about extending your enum with new values.
Please specify more clearly what "broken" is supposed to mean.
Update: so you need to have distinct sets of bands for different types of stars - this can be implemented using distinct enums extending a common interface, e.g.:
interface Band {
String getName();
void doStuff();
...
}
enum BandsVI implements Band {
V, I;
public String getName() { return toString(); }
public void doStuff() { /* do stuff as appropriate for these bands */ }
...
}
enum BandsJHK implements Band {
J, H, K;
public String getName() { return toString(); }
public void doStuff() { /* do stuff as appropriate for these bands */ }
...
}
And you can use these by making your Star class generic:
class Star<T extends Enum<T> & Band> {
private Class<T> bandType;
public Star(Class<T> bandType) { this.bandType = bandType; }
public void printBandNames() {
for (Band b : bandType.getEnumConstants())
System.out.println(b.getName());
}
public void doStuffOnAllBands() {
for (Band b : bandType.getEnumConstants())
b.doStuff();
}
}
...
Star<BandsVI> star1 = new Star<BandsVI>(BandsVI.class);
Star<BandsJHK> star2 = new Star<BandsJHK>(BandsJHK.class);
star1.printBandNames(); // prints V I
star2.printBandNames(); // prints J H K
This works nicely if the bands are organized into distinct groups. If there are stars with mixed band groups, however, you might prefer an alternative approach:
class Star {
private List<? extends Band> bandTypes;
public Star(List<? extends Band> bandTypes) { this.bandTypes = bandTypes; }
public void printBandNames() {
for (Band b : bandTypes)
System.out.println(b.getName());
}
...
}
...
Star star1 = new Star(Arrays.asList(BandsVI.values()));
Star star3 = new Star(Arrays.asList(new Band[]{BandsVI.V, BandsVI.I, BandsJHK.K}));
...
This allows you to set up stars with an arbitrary mix of bands. However, this way you can't use EnumSet or EnumMap on the bands.
All enums implicitly extend java.lang.Enum. Since Java does not support multiple inheritance an enum cannot extend anything else. - http://download.oracle.com/javase/tutorial/java/javaOO/enum.html
This is what I'd do (pseudo-code):
class Band
{
String name;
};
static Band J("J");
static Band K("K");
static ArrayList<Band> JK;
static ArrayList<Band> IHL;
class Star
{
Star(ArrayList<Band> bands)
}
This way you can add bands by just creating more Band objects. Each start has the list of bands it uses so it can iterate over all them.
I am learning Enums in java I like to know what are the major differences of Enum in java and C++.
Thanks
In c++ an enum is just a list of integer values.
In java an enum is a class which extends Enum and is more a nice way to write:
class MyEnum extends Enum<MyEnum>
{
public final static MyEnum VE01 = new MyEnum();
public final static MyEnum VE02 = new MyEnum();
}
as enum:
enum MyEnum
{
VE01,VE02;
}
For the Methods of enum see this.
Since a java enum is an object it supports everything a normal java object does.
as giving them values or functions:
enum Binary{
ZERO(0),ONE(1);
Binary(int i)
{
value = i;
}
public final int value;
}
a nice one is anonymous classes:
enum State{
StateA{
public State doSomething()
{
//state code here
return StateB;
}
},
StateB{
public State doSomething()
{
return StateA;
}
};
public abstract State doSomething();
}
In C++, an enumeration is just a set of named, integral constants. In Java, an enumeration is more like a named instance of a class. You have the ability to customize the members available on the enumeration.
Also, C++ will implicitly convert enum values to their integral equivalent, whereas the conversion must be explicit in Java.
More information available on Wikipedia.
Enums in C/C++ are plain Integers.
Enums in Java are objects - they can have methods (with different behavior from one enum instance to the other). Moreoever, the enum class supplies methods which allows iteration over all enum instances and lookup of an enum instance.
C++:
typedef enum { Red, Yellow, Green } Colors;
void canCrossIntersection(Colors c) {
return c == Green;
}
Java:
public enum Colors {
RED(false),
Yellow(false),
Green(true)
;
Color(boolean b) { this.b = b; }
private boolean b;
public boolean canCrossIntersection() { return b; }
}
In Java you can even emulated extensible enums by letting them implement the same interface and then add all of their values to some sort of collection by calling their values() method.
For a semi-answer... C++0x Strongly Typed Enums bring many of the benefits of Java Enums to C++: strong typing, scope and so forth. If your compiler supports C++0x Strongly Typed Enums, you should consider using them.
Reference:
http://www2.research.att.com/~bs/C++0xFAQ.html#enum
A great feature of Java Enums which lacks in C++ is the name() method. This way you can get the Enum value name (as written in the enum definition) without any extra line of code in definition. For example:
enum Type {T1, T2, T3}
Type t = Type.T1;
System.out.println(t.name()); // prints T1