Java enums and generics - java

This thing is troubling me for a while now. I have asked questions before, but probably with a bad phrasing and an example that was too abstract. So it wasn't clear what I was actually asking. I'll try again. And please don't jump to conclusions. I expect that the question is not easy at all to answer!
why can't I have an enum with generic type parameters in Java?
The question is not about why it's not possible, syntactically. I know it's just not supported. The question is: why did the JSR people "forget" or "omit" this very useful feature? I can't imagine a compiler-related reason, why it wouldn't be feasible.
Here's what I would love to do. This is possible in Java. It's the Java 1.4 way to create typesafe enums:
// A model class for SQL data types and their mapping to Java types
public class DataType<T> implements Serializable, Comparable<DataType<T>> {
private final String name;
private final Class<T> type;
public static final DataType<Integer> INT = new DataType<Integer>("int", Integer.class);
public static final DataType<Integer> INT4 = new DataType<Integer>("int4", Integer.class);
public static final DataType<Integer> INTEGER = new DataType<Integer>("integer", Integer.class);
public static final DataType<Long> BIGINT = new DataType<Long> ("bigint", Long.class);
private DataType(String name, Class<T> type) {
this.name = name;
this.type = type;
}
// Returns T. I find this often very useful!
public T parse(String string) throws Exception {
// [...]
}
// Check this out. Advanced generics:
public T[] parseArray(String string) throws Exception {
// [...]
}
// Even more advanced:
public DataType<T[]> getArrayType() {
// [...]
}
// [ ... more methods ... ]
}
And then, you could use <T> in many other places
public class Utility {
// Generic methods...
public static <T> T doStuff(DataType<T> type) {
// [...]
}
}
But these things are not possible with an enum:
// This can't be done
public enum DataType<T> {
// Neither can this...
INT<Integer>("int", Integer.class),
INT4<Integer>("int4", Integer.class),
// [...]
}
Now, as I said. I know these things have been designed exactly that way. enum is syntactic sugar. So are generics. Actually, the compiler does all the work and transforms enums into subclasses of java.lang.Enum and generics into casts and synthetic methods.
but why can't the compiler go further and allow for generic enums??
EDIT:
This is what I would expect as compiler-generated Java code:
public class DataType<T> extends Enum<DataType<?>> {
// [...]
}

I'm going to guess a bit and say that it is because of covariance issues on the type parameter of the Enum class itself, which is defined as Enum<E extends Enum<E>>, although it is a bit much to investigate all the corner cases of that.
Besides that, a primary use case of enums is with things like EnumSet and valueOf where you have a collection of things with different generic parameters and get the value from a string, all of which would not support or worse the generic parameter on the enum itself.
I know I'm always in a world of pain when I try to get that fancy with Generics, and I imagine the language designers peeked at that abyss and decided to not go there, especially since the features were developed concurrently, which would mean even more uncertainty for the Enum side of things.
Or put another way, it would have all the problems of Class<T> in dealing with classes which themselves have generic parameters, and you would have to do a lot of casting and dealing with raw types. Not truly something that the language designers felt was worth it for the type of use case you are looking at.
EDIT: In response to the comments (and Tom - a downvote?), nested generic parameter makes all kinds of bad things happen. Enum implements Comparable. That simply would not work to compare two arbitrary elements of the enum in client code if generics were in play. Once you deal with a Generic parameter of a Generic parameter, you end up with all kinds of bounds problems and headaches. It is hard to design a class that handles it well. In the case of comparable, I could not figure out a way to make it work to compare two arbitrary members of an enum without reverting to raw types and getting a compiler warning. Could you?
Actually the above is embarrassingly wrong, as I was using the DataType in the question as my template for thinking about this, but in fact an Enum would have a subclass, so that isn't quite right.
However, I stand by the gist of my answer. Tom brought up EnumSet.complementOf and of course we still have valueOf that produces problems, and to the degree that the design of Enum could have worked, we have to realize that that is a 20/20 hindsight thing. Enum was being designed concurrently with generics and didn't have the benefit of validating all such corner cases. Especially considering that the use case for an Enum with a generic parameter is rather limited. (But then again, so is the use case for EnumSet).

I don't think it is impossible to have generified enum. If you could hack into compiler, you can have a subclass of Enum that is generic, and the class file of your generic enum wouldn't cause problems.
But in the end, enum is pretty much a syntax sugar. In C, C++, C#, enums are basically alias for int constants. Java gives it more power, but it is still supposed to represent simple items.
Somewhere people have to draw the line. Just because a class has enumerated instances, doesn't mean it must be an enum. If it is sophisticated enough in other areas, it deserves to be a regular class.
In your case, there is not much advantage to make DataType an enum. You can use enum in switch-case, that's about it, big deal. The non-enum verion of DataType works just fine.

This is how I think of it -
Regular classes have instances. You create a new instance of a class use it for some purpose and then dispose it. For example List<String> is a list of strings. I can do what ever I want to do with strings and then when I am done I can later do the same functionality with integers.
To me enumerators are not types that you create instances of. Its same thing as a singleton. So I can see why JAVA wouldn't allow generics for Enums because you really can't create a new instance of type Enum to use temporary like you do with classes. Enums are supposed to be static and only have one instance globally. To me, it wouldn't make sense to allow generics for a class that only has one instance globally.
I hope this helps.

I think that the reason why you wish to parameterize the enum with <T> boils down to being able to have different method signatures for the various constants of the enum.
In your example, the signature (type of parameters and return type) for parse would be:
for Datatype.INT: int parse(String)
for Datatype.VARCHAR: String parse(String)
and so on
So how would the compiler be able to typecheck something like:
Datatype type = ...
...
int x = type.parse("45");
???
To apply static typing and typechecking to this kind of expression, the signature of the method must be the same for all the instances. However, in the end you suggest to have different method signatures for different instances... That's why it's not possible to do it in Java.

public enum GenericEnum<T> {
SIMPLE, COMPLEX;
public T parse(String s) {
return T.parse(s);
}
}
public void doSomething() {
GenericEnum<Long> longGE = GenericEnum<Long>.SIMPLE;
GenericEnum<Integer> intGE = GenericEnum<Integer>.SIMPLE;
List<Long> longList = new LinkedList<Long>();
List<Integer> intList = new LinkedList<Integer>();
assert(longGE == intGE); // 16
assert(stringList.equals(intList)); // 17
Object x = longGE.parse("1"); // 19
}
The asserts at line 16 and 17 are both true. The generic types are not available at run time.
One of the advantages of an enum is that you can use == to compare them. The assert at line 16 will evaluate to true.
At line 19 we run into a problem though. longGE and intGE are the same object (as the assert at line 16 shows.) What will be returned by the parse("1")? The generic type information is not available at run time. So there would be no way to determine T for the parse method at run time.
Enums are basically static, they only exist once. And it doesn't make sense to apply generic typing to static types.
I hope this helps.
Note - this is not meant to be working code. It is using the syntax suggested in the original question.

Related

How to promise type safety to the compiler in Java

How can I give a promise to the compiler that what I am doing is type safe?
I have a class "Container" that can have some info. I extend said class into what I will refer to as EContainer (E for Extended) and define that it can have some specific info, like say an int and a string. Now, I want to be able to make a list of EContainers and sort it by either int or string, and my solution was to have a ContainerList<T> class where T is what you sort by, and you pass in a lambda to act as an adapter for EContainer to extract T.
So far so good, however now say I want to delimit the list in some way into groups, so if the hypothetical EContainer has ints ranging from 0 to 100, I would want to say "group EContainers like this: 0-20, 21-50, 51-100".
My initial guess was that I would add a function I'll refer to as getDelimiter inside EContainer that would be able to return the "group" it is in, utilizing a protected predefined enum that would define delimiters, however, this is where I ran into problems - the way I would return a group is by having a shared value of T that multiple EContainers would return after running getDelimiter, and so I would group based on that, but unfortunately that would mean that getDelimiter would be a multi-type return function and I do not know how exactly I would tell the compiler that "yes, I know what I am doing, and that I will definitely get back T from getDelimiter"
I could probably get around this by adding another lambda in there that would define the function to call on the EContainer to get the delimiter function, and that should be type safe and everything, but I thought that would end up in an unnecessary boilerplate in EContainer, so maybe there is a better option I don't know of? I have to say, it is very difficult to find the keywords I could use for this problem, so I couldn't do much initial research.
Edit: Just had an idea of having getDelimiter return everything as Object and then casting to T right after, sounds like that should work and would minimize boilerplate.
How can I give a promise to the compiler that what I am doing is type safe?
Generally speaking, that is what the #SuppressWarnings("unchecked") does.
It is not clear if it will work for your use-case. (Show us your actual code ... if you want a more specific answer.)
However, there will still be a hidden runtime check to detect that you are not violating runtime type safety. There is no way you can turn off those checks.
Just had an idea of having getDelimiter return everything as Object and then casting to T right after, sounds like that should work and would minimize boilerplate.
Hmm ... you can't cast something statically typed as Object to T. The fundamental problem is that the actual type of T is erased, so the runtime doesn't know what type to cast to.
One possible workaround is to represent the actual type of T as a Class object, and use reflection to do the type check / cast. Indeed, this is the general workaround when you need to do type checks in spite of type erasure. Unfortunately this is cumbersome, because at some point you need to pass an extra explicit Class object as a parameter to make it work.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
public class StackOverflowNonsense {
public static abstract class Container{
public String sharedFunc(){return "this is a shared function";}
}
public static class EContainer{
public int _int; //id=0
public float _float; //id=!0
public EContainer(int _int,float _float){
this._int=_int;
this._float=_float;
}
protected enum Delimiters{
INT(new ArrayList<Object>(Arrays.asList(0,21,51))),
FLOAT(new ArrayList<Object>(Arrays.asList((float)0,(float)0.5,(float)1)));
final ArrayList<Object> delim;
Delimiters(ArrayList<Object> delim){
this.delim=delim;
}
}
public Object getDelimiter(int id){
if (id==0){
int pos=Collections.binarySearch(Delimiters.INT.delim, (Object)_int,Comparator.comparingInt(key->(int)key));
return (Object)Delimiters.INT.delim.get(pos<0?-2-pos:pos);
}else{
int pos=Collections.binarySearch(Delimiters.FLOAT.delim, (Object)_float,Comparator.comparingDouble(key->(Float)key));
return (Object)Delimiters.FLOAT.delim.get(pos<0?-2-pos:pos);
}
}
#Override
public String toString(){
return String.format("EContainer with (%d, %f)", _int,_float);
}
}
public static void main(String[] args){
ArrayList<EContainer> ContainerList=new ArrayList<>(
Arrays.asList(new EContainer(0,(float)2.0),new EContainer(69,(float)0.69))
);
Collections.sort(ContainerList,Comparator.comparingInt(key->(int)key.getDelimiter(0)));
System.out.println(ContainerList);
Collections.sort(ContainerList,Comparator.comparingDouble(key->(Float)key.getDelimiter(1)));
System.out.println(ContainerList);
}
}
This appears to provide the functionality I want, however I'm not sure if this code breaks some holy scripts, so maybe there is a better solution?

When to use static fields and when to use enumerations? [duplicate]

I am very familiar with C# but starting to work more in Java. I expected to learn that enums in Java were basically equivalent to those in C# but apparently this is not the case. Initially I was excited to learn that Java enums could contain multiple pieces of data which seems very advantageous (http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html). However, since then I have found a lot of features missing that are trivial in C#, such as the ability to easily assign an enum element a certain value, and consequently the ability to convert an integer to an enum without a decent amount of effort (i.e. Convert integer value to matching Java Enum).
So my question is this: is there any benefit to Java enums over a class with a bunch of public static final fields? Or does it just provide more compact syntax?
EDIT: Let me be more clear. What is the benefit of Java enums over a class with a bunch of public static final fields of the same type? For example, in the planets example at the first link, what is the advantage of an enum over a class with these public constants:
public static final Planet MERCURY = new Planet(3.303e+23, 2.4397e6);
public static final Planet VENUS = new Planet(4.869e+24, 6.0518e6);
public static final Planet EARTH = new Planet(5.976e+24, 6.37814e6);
public static final Planet MARS = new Planet(6.421e+23, 3.3972e6);
public static final Planet JUPITER = new Planet(1.9e+27, 7.1492e7);
public static final Planet SATURN = new Planet(5.688e+26, 6.0268e7);
public static final Planet URANUS = new Planet(8.686e+25, 2.5559e7);
public static final Planet NEPTUNE = new Planet(1.024e+26, 2.4746e7);
As far as I can tell, casablanca's answer is the only one that satisfies this.
Type safety and value safety.
Guaranteed singleton.
Ability to define and override methods.
Ability to use values in switch statement case statements without qualification.
Built-in sequentialization of values via ordinal().
Serialization by name not by value, which offers a degree of future-proofing.
EnumSet and EnumMap classes.
Technically one could indeed view enums as a class with a bunch of typed constants, and this is in fact how enum constants are implemented internally. Using an enum however gives you useful methods (Enum javadoc) that you would otherwise have to implement yourself, such as Enum.valueOf.
Nobody mentioned the ability to use them in switch statements; I'll throw that in as well.
This allows arbitrarily complex enums to be used in a clean way without using instanceof, potentially confusing if sequences, or non-string/int switching values. The canonical example is a state machine.
The primary advantage is type safety. With a set of constants, any value of the same intrinsic type could be used, introducing errors. With an enum only the applicable values can be used.
For example
public static final int SIZE_SMALL = 1;
public static final int SIZE_MEDIUM = 2;
public static final int SIZE_LARGE = 3;
public void setSize(int newSize) { ... }
obj.setSize(15); // Compiles but likely to fail later
vs
public enum Size { SMALL, MEDIUM, LARGE };
public void setSize(Size s) { ... }
obj.setSize( ? ); // Can't even express the above example with an enum
There is less confusion. Take Font for instance. It has a constructor that takes the name of the Font you want, its size and its style (new Font(String, int, int)). To this day I cannot remember if style or size goes first. If Font had used an enum for all of its different styles (PLAIN, BOLD, ITALIC, BOLD_ITALIC), its constructor would look like Font(String, Style, int), preventing any confusion. Unfortunately, enums weren't around when the Font class was created, and since Java has to maintain reverse compatibility, we will always be plagued by this ambiguity.
Of course, this is just an argument for using an enum instead of public static final constants. Enums are also perfect for singletons and implementing default behavior while allowing for later customization (I.E. the strategy pattern). An example of the latter is java.nio.file's OpenOption and StandardOpenOption: if a developer wanted to create his own non-standard OpenOption, he could.
There are many good answers here, but none mentiones that there are highly optimized implementations of the Collection API classes/interfaces specifically for enums:
EnumSet
EnumMap
These enum specific classes only accept Enum instances (the EnumMap only accept Enums only as keys), and whenever possible, they revert to compact representation and bit manipulation in their implementation.
What does this mean?
If our Enum type has no more that 64 elements (most of real-life Enum examples will qualify for this), the implementations store the elements in a single long value, each Enum instance in question will be associated with a bit of this 64-bit long long. Adding an element to an EnumSet is simply just setting the proper bit to 1, removing it is just setting that bit to 0. Testing if an element is in the Set is just one bitmask test! Now you gotta love Enums for this!
example:
public class CurrencyDenom {
public static final int PENNY = 1;
public static final int NICKLE = 5;
public static final int DIME = 10;
public static final int QUARTER = 25;}
Limitation of java Constants
1) No Type-Safety: First of all it’s not type-safe; you can assign any valid int value to int e.g. 99 though there is no coin to represent that value.
2) No Meaningful Printing: printing value of any of these constant will print its numeric value instead of meaningful name of coin e.g. when you print NICKLE it will print "5" instead of "NICKLE"
3) No namespace: to access the currencyDenom constant we need to prefix class name e.g. CurrencyDenom.PENNY instead of just using PENNY though this can also be achieved by using static import in JDK 1.5
Advantage of enum
1) Enums in Java are type-safe and has there own name-space. It means your enum will have a type for example "Currency" in below example and you can not assign any value other than specified in Enum Constants.
public enum Currency {PENNY, NICKLE, DIME, QUARTER};
Currency coin = Currency.PENNY;
coin = 1; //compilation error
2) Enum in Java are reference type like class or interface and you can define constructor, methods and variables inside java Enum which makes it more powerful than Enum in C and C++ as shown in next example of Java Enum type.
3) You can specify values of enum constants at the creation time as shown in below example:
public enum Currency {PENNY(1), NICKLE(5), DIME(10), QUARTER(25)};
But for this to work you need to define a member variable and a constructor because PENNY (1) is actually calling a constructor which accepts int value , see below example.
public enum Currency {
PENNY(1), NICKLE(5), DIME(10), QUARTER(25);
private int value;
private Currency(int value) {
this.value = value;
}
};
Reference: https://javarevisited.blogspot.com/2011/08/enum-in-java-example-tutorial.html
The first benefit of enums, as you have already noticed, is syntax simplicity. But the main point of enums is to provide a well-known set of constants which, by default, form a range and help to perform more comprehensive code analysis through type & value safety checks.
Those attributes of enums help both a programmer and a compiler. For example, let's say you see a function that accepts an integer. What that integer could mean? What kind of values can you pass in? You don't really know right away. But if you see a function that accepts enum, you know very well all possible values you can pass in.
For the compiler, enums help to determine a range of values and unless you assign special values to enum members, they are well ranges from 0 and up. This helps to automatically track down errors in the code through type safety checks and more. For example, compiler may warn you that you don't handle all possible enum values in your switch statement (i.e. when you don't have default case and handle only one out of N enum values). It also warns you when you convert an arbitrary integer into enum because enum's range of values is less than integer's and that in turn may trigger errors in the function that doesn't really accept an integer. Also, generating a jump table for the switch becomes easier when values are from 0 and up.
This is not only true for Java, but for other languages with a strict type-checking as well. C, C++, D, C# are good examples.
An enum is implictly final, with a private constructors, all its values are of the same type or a sub-type, you can obtain all its values using values(), gets its name() or ordinal() value or you can look up an enum by number or name.
You can also define subclasses (even though notionally final, something you can't do any other way)
enum Runner implements Runnable {
HI {
public void run() {
System.out.println("Hello");
}
}, BYE {
public void run() {
System.out.println("Sayonara");
}
public String toString() {
return "good-bye";
}
}
}
class MYRunner extends Runner // won't compile.
enum Benefits:
Enums are type-safe, static fields are not
There is a finite number of values (it is not possible to pass non-existing enum value. If you have static class fields, you can make that mistake)
Each enum can have multiple properties (fields/getters) assigned - encapsulation. Also some simple methods: YEAR.toSeconds() or similar. Compare: Colors.RED.getHex() with Colors.toHex(Colors.RED)
"such as the ability to easily assign an enum element a certain value"
enum EnumX{
VAL_1(1),
VAL_200(200);
public final int certainValue;
private X(int certainValue){this.certainValue = certainValue;}
}
"and consequently the ability to convert an integer to an enum without a decent amount of effort"
Add a method converting int to enum which does that. Just add static HashMap<Integer, EnumX> containing the mapping.
If you really want to convert ord=VAL_200.ordinal() back to val_200 just use: EnumX.values()[ord]
You get compile time checking of valid values when you use an enum. Look at this question.
The biggest advantage is enum Singletons are easy to write and thread-safe :
public enum EasySingleton{
INSTANCE;
}
and
/**
* Singleton pattern example with Double checked Locking
*/
public class DoubleCheckedLockingSingleton{
private volatile DoubleCheckedLockingSingleton INSTANCE;
private DoubleCheckedLockingSingleton(){}
public DoubleCheckedLockingSingleton getInstance(){
if(INSTANCE == null){
synchronized(DoubleCheckedLockingSingleton.class){
//double checking Singleton instance
if(INSTANCE == null){
INSTANCE = new DoubleCheckedLockingSingleton();
}
}
}
return INSTANCE;
}
}
both are similar and it handled Serialization by themselves by implementing
//readResolve to prevent another instance of Singleton
private Object readResolve(){
return INSTANCE;
}
more
Another important difference is that java compiler treats static final fields of primitive types and String as literals. It means these constants become inline. It's similar to C/C++ #define preprocessor. See this SO question. This is not the case with enums.
Enums can be local
As of Java 16, an enum can be defined locally (within a method). This scope is in addition to being able to define an enum as nested or as separate class.
This new local definition scope came along with the new records feature. See JEP 395: Records for details. Enums, interfaces, and records can all be defined locally in Java 16+.
In contrast, public static final fields always have global scope.
I think an enum can't be final, because under the hood compiler generates subclasses for each enum entry.
More information From source
There are many advantages of enums that are posted here, and I am creating such enums right now as asked in the question.
But I have an enum with 5-6 fields.
enum Planet{
EARTH(1000000, 312312321,31232131, "some text", "", 12),
....
other planets
....
In these kinds of cases, when you have multiple fields in enums, it is much difficult to understand which value belongs to which field as you need to see constructor and eye-ball.
Class with static final constants and using Builder pattern to create such objects makes it more readable. But, you would lose all other advantages of using an enum, if you need them.
One disadvantage of such classes is, you need to add the Planet objects manually to the list/set of Planets.
I still prefer enum over such class, as values() comes in handy and you never know if you need them to use in switch or EnumSet or EnumMap in future :)
Main reason: Enums help you to write well-structured code where the semantic meaning of parameters is clear and strongly-typed at compile time - for all the reasons other answers have given.
Quid pro quo: in Java out of the box, an Enum's array of members is final. That's normally good as it helps value safety and testing, but in some situations it could be a drawback, for example if you are extending existing base code perhaps from a library. In contrast, if the same data is in a class with static fields you can easily add new instances of that class at runtime (you might also need to write code to add these to any Iterable you have for that class). But this behaviour of Enums can be changed: using reflection you can add new members at runtime or replace existing members, though this should probably only be done in specialised situations where there is no alternative: i.e. it's a hacky solution and may produce unexpected issues, see my answer on Can I add and remove elements of enumeration at runtime in Java.
You can do :
public enum Size { SMALL(1), MEDIUM(2), LARGE(3) };
private int sizeValue;
Size(sizeValue) {this.sizeValue = value; }
So with this you can get size value like this SMALL.getSizeValue();
If you want to set sizes Enums are not for you, if you will be only define constants and fixed values are fine.
Check this link maybe can help you

Arithmetic with generic Numbers

So I have to accept a generic type T, which will be a wrapper class for one of the numeric primitives, and do some arithmetic with it. I thought this would be trivial because of autoboxing and unboxing:
T newval = val1*val2;
(Where val1 and val2 are already variables of type T with appropriate values in them.)
But it turns out that Java won't unbox values if it doesn't know the type explicitly at compile time. I also thought that I could just use the multiply method that each of the Number subclasses (that I intend to use) have within them. So I declared my class with:
public class SomeClass<T extends Number> {
// ...
}
and then:
T newval = val1.multiiply(val2);
But that doesn't work because I guess not all subclass' of Number are required (Why don't they use an interface for this?) to have that method (yet all the ones that I want to use DO.)
I've seen some similar questions but they all resulted in OP being told to just not use generics, yet I am required to use generics for the work I'm doing, otherwise the entire thing is worthless. Can anybody think of a solution that will work for me?
EDIT:
Okay so he got back to me and clarified what was meant, it's different enough that my question is no longer relevant to what i'm doing. Thanks guys.
The various arithmetic operators can only be applied to values of types that are convertible to primitive types. There is no way to express that requirement with generics. Therefore generics are not suited for this task.
For generics methods, instead provide overloads for the numeric primitive types.
For generic classes, provide subclasses that use a specific numeric type.
class NumericCalculator<T> {
public void calculate(T one, T two) {
T result = one * two; // compiler error
}
}
class LongCalculator extends NumericCalculator<Long> {
public void calculate(Long one, Long two) {
Long result = one * two; // yes
}
}
The implementation that uses the operators will have to be in the subclasses which know the actual type.

What does the <TYPE> in java mean?

I have seen declarations, interfaces and classes that go TYPE<CLASS>
What does this do/mean?
Without evidence, I believe you're talking about Java's Generics support...
Generics allow you to abstract over types
Before Java 5 it was difficult to provide classes that were capable of supporting multiple different types of Objects without having to code for each specific situation, so it was common for people to pass Object instead.
This leads to many difficult choices to make at runtime, you'd have to do a runtime check to see if it was possible to cast a given Object to a usable type...for example
List myIntList = new LinkedList(); // 1
myIntList.add(new Integer(0)); // 2
Integer x = (Integer) myIntList.iterator().next(); // 3
Now, this is reasonably obvious, but if you were passed just a List, you'd have to check each and every element in the list for correctness...
But now, we can do this...
List<Integer> myIntList = new LinkedList<Integer>(); // 1'
myIntList.add(new Integer(0)); // 2'
Integer x = myIntList.iterator().next(); // 3'
This is a contract that basically says "This list only contains Integer type's of objects".
With generics you can construct a single class that is capable of handling multiple different data types or a family of data types (ie constraint the parameter so that it must be extended from a particular parent type).
Iterator<? extends Number> itNum;
Basically says, this will contain objects that inherit from Number, include Integer, Long, Double, Float...
Often in method and class decelerations you will see something similar to...
public class MyGenericClass<T> {...}
or
public class MyGenericClass<T extends MyBaseObject> {...}
This allows you to refer to T as if it were a concrete object type, for example...
public class MyGenericClass<T extends MyBaseObject> {
private T value;
public MyGenericClass(T value) {
this.value = value;
}
}
This allows the compiler (and JVM) to essentially "replace" the marker T with a concert type (okay, it's a little more complicated then that, but that's the magic)...
This allows to do things like...
... new MyGenericClass<MySuperObject>(new MySuperObject());
... new MyGenericClass<MySuperSuperObject>(new MySuperSuperObject());
And know that it will only ever accept the type of object I specify...
Have a read through the link in the first paragraph, I'm sure it can do more justice then I can ;)
public class Grid<E> {
That's how you define a generic class in Java.Grid is the class and E is a formal type parameter.
If you are really interested in learning about it, you will find a very good reference here - Java Generics FAQs - Frequently Asked Questions
that is generic types check it here.
Simple examples would be
List<String>
Map<Integer, String>
It's unclear what you are asking without looking at what exactly you are seeing. But it's likely you are seeing Generics in Java. Learn more about it here
The idea is basically to make stronger type-safety in Java. So, a declaration like List<Integer> intList means intList has Integers in it. And if you try to put a, say, String -- it will throw compilation error.

What is the purpose of Enum class which was introduced in Java 5?

My suggestions:
1) either enums exist only before compilation (like generics; but I've never heard anything about it whilst it's written everywhere that generics are being erased after compilation)
2) or Enum is a way to maintain backward compatibility in some way (but I don't see that way yet).
Any other suggestions? (btw, have you ever used it in your code?)
UPD: http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Enum.html
In other words, there's a enum keyword and Enum class. They both appeared in Java 5. The question: why do we need both?
The second question: why Enum became a part of the API?
From the Java Tutorials:
You should use enum types any time you need to represent a fixed set of constants. That includes natural enum types such as the planets in our solar system and data sets where you know all possible values at compile time—for example, the choices on a menu, command line flags, and so on.
Enums are extremely useful, and yes, I have used them plenty of times in my code.
Edit:
...there's a enum keyword and Enum class. They both appeared in Java 5. The question: why do we need both?
This question is analogous to asking "there's a class keyword and an Object class. Why do we need both?"
In both cases, the keywords are basically hints to the compiler; you could think of them as syntactic sugar that saves you keystrokes, and lets the compiler do less work (by not making it guess about what you're declaring).
See this q&a as well.
...have you ever used it in your code?
The answer is still "yes." In particular, Enum#valueOf() is a static method useful for parsing strings:
DayOfWeek d = Enum.valueOf(DayOfWeek.class, "TUESDAY");
but of course this works, too:
DayOfWeek d = DayOfWeek.valueOf("TUESDAY");
Enums exist to represent type-safe enumerations (much better than using int constants for the same thing).
If you're asking what the purpose of the Enum class itself is - it's to act as the superclass for the user-defined enums. Each enum is compiled into a class that extends Enum with the appropriate generic parameter (i.e. itself).
Why is this done via syntactic sugar rather than simple subclassing? For one, it enforces the specific syntax that enums have (static instances forming the enum members). Another reason might be that the generic manipulations required to subclass Enum<E extends Enum<E>> would be very confusing to developers who had never seen any generics before. By hiding this complexity behind a new keyword, developers wouldn't have to decipher it themselves. Finally, the keyword implies that it's a special construct that shouldn't really be treated the same as a normal class.
In my humble opinion, the main thing enums are good for is type safety.
Suppose you have a function which can be called with some option that has a fixed set of possibilities. Say, "sale" or "return". A really bad solution would be to pass in a string, like:
public void doTransaction(String type)
{
if (type.equals("sale"))
... do whatever ...
}
One big catch to this method is if someone were to try calling it with "Sale" or "sail". Unless the program verifies that only valid parameters are passed in, misspellings could give mysterious bugs.
So okay, many programmers created constants for this:
public final static int SALE=1, RETURN=2;
public void doTransaction(int type)
{
if (type==SALE)
... do whatever ...
}
That's much better, but it still has problems. Suppose we have two parameters:
public final static int SALE=1, RETURN=2;
public final static int DOMESTIC=1, FOREIGN=2;
public void doTransaction(int type, int locale)
{
if (type==SALE && locale==DOMESTIC)
... etc ...
}
Now someone gets confused and calls doTransaction(FOREIGN, SALE). This will compile successfully, pass any validity tests within the program, and give totally incorrect results. Because if you didn't catch it, the parameters are in the wrong order.
Enums solve this problem. If instead you write
enum SaleType {SALE, RETURN};
enum Locale {DOMESTIC, FOREIGN};
public void doTransaction(SaleType type, Locale locale)
... etc ...
Now if someone tries to write, doTransaction(Locale.FOREIGN, SaleType.SALE), they get a compile-time error, and immediately know that they have the parameters wrong.
Enum was added so the functionality provided by enum is visable and documented. What would be gained by hiding this class?
generics are not erased after compilation.
Not sure why an Enum class would be needed for backward compatibility.
I have used the class to read what Enums do and in code to check for Enum type, valueOf etc.
Ironically, this question was posted just before yours. It shows examples of using the class. Checking if a class is java.lang.Enum
either enums exist only before
compilation
This is true, if you're talking about the enum syntax in the declaration, as opposed to the class syntax. At the bytecode level, Java enums are classes just like any other class. The enum semantics are basically implemented by the Java compiler.
Here you have some answers
http://www.myhomepageindia.com/index.php/2009/07/08/enums-in-java-5-code-examples.html
See a full list of reasoning at their Javadoc
I am not sure about #2. But I use Enums all the time in Java. Instead of doing
public static final int OPTION_ONE = 1;
public static final int OPTION_TWO = 2;
You can do
public enum Option{one, two}
This is much cleaner because now you can declare all your funcitons like so:
public void doSomething(Option o);
Where as the old way, you had to do public void doSomething(int i) and I could have passed any integer. Therefore, the parameter was never check to make sure it is a valid option. This allows for much cleaner code at compile time and run time.
I also use Enum a lot when it gets to doing variations of the same things. Let's say we have a sort attribute.
You can do something like this which is very clean and much BETTER than case statements.
public enum Sort {
Everyone {
#Override
List<Checkin> refreshList(Client client, Location location) throws IOException {
return client.checkins().getList();
}
},
NearBy {
#Override
List<Checkin> refreshList(Client client, Location location) throws IOException {
return client.checkinsNear(location.getLatitude(), location.getLongitude()).getList();
}
}; // and any other sorts
abstract List<Checkin> refreshList(Client client, Location location) throws IOException;
}

Categories

Resources