I want to parameterize a class with an enum, then in the constructor of the class create an Array having the size of the number of elements in the enum.
I created the class like this:
public class LogLine <T extends Enum<T>> {
And then in the constructor I tried writing this:
public LogLine(){
numberOfElementsInEnum = T.values().length;
//then I would create the Array based on the numberOfElementsInEnum variable
It doesn't work. The compiler doesn't see the values method.
I tried with T extending String instead of Enum. All static method are then accessible.
What is the issue here?
You have to declare a constructor that accepts the Class:
public LogLine(Class<T> c) {
numberOfElementsInEnum = c.getEnumConstants().length;
}
See also here: https://docs.oracle.com/javase/tutorial/reflect/special/enumMembers.html
You don't strictly "have to" pass the class to the constructor. In some cases this is a needless inconvenience for the person instantiating your class.
It all depends on your interface.
If your interface is purely a consumer of items (and given that you're logging, I suspect it might be), then you can get away with lazily calculating the number of values at the point when you're actually consuming the item.
class LogLine<T extends Enum<T>>
{
public void add(T item)
{
int numberOfElementsInEnum = item.getDeclaringClass().getEnumConstants().length;
}
}
We would need know your requirements and to see the rest of your implementation of LogLine to say whether this approach is suitable.
Related
I have a beginners question concerning Java.
I have a class Thing<T> that has an attribute "attribute".
I want the attribute to be either a LinkedList<T> (as given by Java) or a self-defined type named My_Type<T>, depending on the boolean that is given to the constructor of Thing. Like this:
public class Thing<T> {
private ??? attribute; // Type is not given yet. How do I do this?
public Thing(boolean which) {
if (which)
attribute = new LinkedList<T>();
else
attribute = new My_Type<T>();
}
...
}
Thing has some more methods that use add and remove, which are both implemented for LinkedList and My_Type.
How do I declare my attribute? Declaring it as Object is no option because Object does not know the methods add and remove. I thought about using interfaces, but I don't know how.
If both LinkedList and My_Type were written by me, I could let them both implement the interface LinkedListOrMy_Type<T> which has add and remove as methods. Then, instead of
private ??? attribute;
I would write
private LinkedListOrMy_Type<T> attribute;
And everything would be okay. But because I cannot modify the code of LinkedList, I don't know how to work around this. Any suggestions?
Making My_Type implement the List interface (given by Java) is not an option either, because there are so many methods that I would need to implement into My_Type. But I only want add and remove. I know it's a possible workaround - I could let My_Type throw an UnsupportedOperationException in every method of List except add and remove. But I believe I could learn more about good programming if you give me a suggestions that is not as dirty as this!
You can't have one field that can be of two different types in Java; the closest you can do is have a field that is some common base type. So you have a few options.
Use a common base type that provides add and remove. The obvious candidate for this is Collection, which is implemented by LinkedList.
Use a common base type that does not provide the methods you want, but cast the object when you need to. In this case you could simply have a field of type Object, and each time you want to make use of your field, you have to cast it to either of the actual types.
Use two fields. This would seem to make more sense - having one variable of two different types is not really how variables work.
Wrap LinkedList and MyType in classes that have a common base type that provides the methods you need.
For instance:
interface WrapperThing<T> {
void add(T item);
void remove(T item);
}
class ListWrapperThing<T> implements WrapperThing<T> {
private List<T> list;
public ListWrapperThing() {
list = new LinkedList<T>();
}
public void add(T item) {
list.add(item);
}
public void remove(T item) {
list.remove(item);
}
}
class MyTypeWrapperThing<T> implements WrapperThing<T> {
private MyType<T> my;
public ListWrapperThing() {
my = new MyType<T>();
}
public void add(T item) {
my.add(item);
}
public void remove(T item) {
my.remove(item);
}
}
Then you can use a WrapperThing<T> variable much as if it were a variable that could (inside it) contain either a List or a MyType object.
Going the interface route seems a good idea. Define your own interface MyInterface and let MyType implement it:
class MyType implements MyInterface
Now here's the trick: LinkedList isn't final! Use OOP to your advantage by extending the JDK class and letting it implement your interface:
class MyLinkedList extends LinkedList implements MyInterface
Let us know if this will do the trick for you...
Well, you could implement the interface List in your type. It is implemented by all list like classes in Java. Of course it offers more methods than you probably need, but you could implement only those you need and throw for example an not implemented exception in others.
Situation: May Field be a property of a Model which I want to observe (something similar to PropertyChangeListener). Field is defined as Enum. I want to call
someModel.getField(Field f).addObserver(FieldObserver<Something> observer)
the Observer's type ("Something") depends on the Field and I want to force typesafety. For example Field.FIRST_NAME would take a FieldObserver< String>.
First (working) approach:
I could already reach it by defining Field as generic class with public static final fields, instead of enum. So I have a Field, which I can use to force type safety like this:
public <E> Observable<E> getField(Field<? extends E> f)
with method in Observable<E>: void addObserver(FieldObserver<? super E> observer)
Now the following line causes a compile time error, which is what I want:
someModel.getField(Field.some_STRING_field).addObserver(INTEGERObserver)
Second (not working yet) approach:
I am trying now to implement the same behaviour with the enum class. One of my approach is:
public enum Field{
FIRST_NAME("firstName") {
#Override
public Observable<String> getObservable() {
return new Observable<String>();
}
},...
//every Field must implement:
public abstract FieldObservable.Observable<?> getObservable();`
}
//getField(Field f) of the Model-class:
public Observable<?> getField(Field f){
return f.getObservable();
}
Trying to add a FieldObserver of any type (also the correct one) gives me a compile time error like this:
addObserver (enumer.FieldObserver< capture< ?>>) in Observable cannot be applied
to (enumer.FieldObserver< java.lang.String>)
Can someone tell me how to make the enum-approach work? Also if someone has a better solution or concerns about the approaches, I will be thankful to hear it.
Unfortunately enums cannot be generic. This is because enum is an ordinary class that extends Enum, i.e. its definition looks like the following:
class MyEnum<E extends Enum<E>> extends Enum<E extends Enum> {}
So application programmer cannot add more generic parameter to this class.
I can suggest you the following work arounds:
Make your method generic, ie. define it in enum level as public <T> getField(Class<T> type). Override this method for each enum member. Then you can supply the type at any call of the method.
Do not use enum for this task. Create ordinary class with public static members and private constructor. if you want enum-like behavior implement your own static values() and valueOf().
my problem is:
I have a bunch of different classes all extending a base class (Identifiable).
I need to assign to some of the sub-class a certain value (securityLevel) which should be changeable and assigned to all member of the class (i.e.: it should be static).
I need to access the classes via the common ancestor.
How do I do this?
The first thing which came to mind is to have a dedicated interface (ISecurity) defining either the values or a static method to access them and let the actual classes either not to implements it and, if they do, to override the static field (or method to retrieve it).
However this is not possible for two reasons:
The current Java language does not allow static members in interfaces.
Even if it would allow it it would not be possible to #Override it.
How can I code around the problem?
The only way I found is:
add a non-static member (public Class getValueProvider()) to base class to retrieve the value returning null.
in the interested classes #Override the non-static method returning the value of a private static Class getValueProvider() implementing setters and getters for the wanted value.
use the retrieved class instance to obtain the requested value (or skip everything if the return is null).
This is very ugly and there's no way to enforce the correct implementation in sub-classes.
You could try a service/factory type of implementation. Or have some sort of class object that stores security (SecuritySettings) and send in the current Identifiable object to get security level
public class Identifiable { }
public class SampleUser extends Identifiable { }
public class ExampleUser extends Identifiable { }
public class UserService
{
public int SampleUserSecurity = 0;
//Or an array/dictionary structure
public int GetSecurityLevel(Identifiable user)
{
if(user instanceof SampleUser)
{
return SampleUserSecurity;
}
}
public SampleUser CreateSampleUser()
{
return new SampleUser();
}
public ExampleUser CreateExampleUser()
{
return new ExampleUser();
}
}
You could define Identifiable to be an abstract class. Additionally, you can define another abstract class that extends Identifiable and adheres to your restrictions, ie holds the static variable and whatever methods may be necessary.
I would try to avoid any static members. Static members in java are always clamsy (you cannot override just hide them, etc.)
I'm not sure if I understand your problem corret but I suggest you construct the objects with a context interface or something. The objects then cann access these context interface if they area allowed to return a value or have to return a special value.
The one creating all these objects can pass the same object and so control the behaviour. This object could then be held static (like a singelton)
This is an example which I made up to be a simplification of my real code, so I apologize if it is a little contrived. What I would like to do is to effectively get two type parameters out of a single nested type argument. I'm pretty sure this is impossible, but I thought I'd give it a shot.
//Not legal java code
public class Foo<C extends Collection<T>> { //where T is another type parameter
private C coll;
public Foo(C coll) {
this.coll = coll;
}
public void add(T elem){
this.coll.add(elem);
}
//UPDATED TO ADD GETTER
/**
* I may need to retrieve the collection again, or pass it
* on to another function that needs the specific C type
*/
public C getColl(){
return coll;
}
}
...
List<String> strings = new ArrayList<String>();
Foo<List<String>> foo = new Foo<List<String>>(strings);
foo.add("hello");
I know that I could do it by adding another type parameter:
public class Foo<C extends Collection<T>,T>
but then I have to add the redundant:
Foo<List<String>,String> foo = new Foo<List<String>,String>(strings);
And in my real world case, my generics can sometimes be specified in the implements clause like
public class Bar implements Baz<String>
Having to specify that second type parameter is even more painful then, because it feels like it throws the implementation details in my face. Having to say
Foo<Bar,String>
when there is a relationship between String and Bar already, just seems inelegant. I get that its Java, so that goes with the territory, but just curious if there was a solution for this.
It's not possible and I don't think it's ideal anyway because there is nothing in your existing class that requires invariance.
Foo<T,C extends Collection<T>>
could more generally be
Foo<T,C extends Collection<? super T>>
if the only reason to have T is to allow mutation of the collection.
Note, if you're concerned about having to specify two type parameters frequently, you can create a shallow subclass:
class DerivedFoo<T> extends Foo<Collection<T>,T>
and you can use factory methods to avoid having to double-specify at creation time
public static <T> Foo<Collection<T>,T> fromCollection(Collection<T> c)
You can also abstract the interface into an interface to get the benefits of concise types that you get with DerivedFoo above.
Why wouldn't you just use T as your only type parameter, as in:
public class Foo<T> { //where T is another type parameter
private Collection<T> coll;
public Foo(Collection<T> coll) {
this.coll = coll;
}
public void add(T elem){
this.coll.add(elem);
}
Prior to Java7, constructors don't do type inference, the workaround is to have a static factory method. That's no longer necessary. In Java 7 you can
Foo<List<String>,String> foo = new Foo<>(strings);
Regarding T and C, if we have 2 type parameters with constraints between them, there got to be some degree of redundancy. In your example, since one parameter C totally dictates the another parameter T, the redundancy seems unbearable. I don't see a solution.
But you probably can feel better if the type parameters are reordered
Foo<String,Bar> foo = new Foo<>(bar);
so we declare String first; then further provide a Baz<String> which is Bar
public static void main(String[] args) {
List<? extends Object> mylist = new ArrayList<Object>();
mylist.add("Java"); // compile error
}
The above code does not allow you to add elements to the list and wild cards can only be used as a signature in methods, again not for adding but only for accessing.
In this case what purpose does the above fulfil ??
Let's say you have an interface and two classes:
interface IResult {}
class AResult implements IResult {}
class BResult implements IResult {}
Then you have classes that return a list as a result:
interface ITest<T extends IResult> {
List<T> getResult();
}
class ATest implements ITest<AResult> {
// look, overridden!
List<AResult> getResult();
}
class BTest implements ITest<BResult> {
// overridden again!
List<BResult> getResult();
}
It's a good solution, when you need "covariant returns", but you return collections instead of your own objects. The big plus is that you don't have to cast objects when using ATest and BTest independently from the ITest interface. However, when using ITest interface, you cannot add anything to the list that was returned - as you cannot determine, what object types the list really contains! If it would be allowed, you would be able to add BResult to List<AResult> (returned as List<? extends T>), which doesn't make any sense.
So you have to remember this: List<? extends X> defines a list that could be easily overridden, but which is read-only.
In his book great 'Effective Java' (Second Edition) Joshua Bloch explains what he calls the producer/consumer principle for using generics. Josh's explaination should tell you why your example does not work (compile) ...
Chapter 5 (Generics) is freely available here: http://java.sun.com/docs/books/effective/generics.pdf
More information about the book (and the author) are available: http://java.sun.com/docs/books/effective/
With java generics using wildcards, you are allowed the above declaration assuming you are only going to read from it.
You aren't allowed to add/write to it, because all generic types must be stripped at compile time, and at compile time there isn't a way the compiler knows List are only strings, (it could be any object including strings!)
You are however allowed to read from it since they are going to be at least objects. Mixing different types are not allowed in java collections to keep things clean and understandable, and this helps ensure it.
The point of bounded wildcard types is their use in method signatures to increase API flexibility. If, for example, you implement a generic Stack<E>, you could provide a method to push a number of elements to the stack like so:
public void pushAll(Iterable<? extends E> elements) {
for(E element : elements){
push(e);
}
}
Compared to a pushAll(Iterable<E> elements) signature without a wildcard, this has the advantage that it allows collections of subtypes of E to be passed to the method - normally that would not be allowed because an Iterable<String> is, somewhat counterintuitively, not a subclass of Iterable<Object>.
This works:
List<? super Object> mylist = new ArrayList<Object>();
mylist.add("Java"); // no compile error
From O'Reilly's Java Generics:
The Get and Put Principle: use an extends wildcard when you only get values our of a structure, use a super wildcard when you only put values into a structure, and don't use a wildcard you both get and put.
List<? extends Object>, which is the same as List<?>, fulfills the purpose of generalizing all types List<String>, List<Number>, List<Object>, etc. (so all types with a proper type in place of the ?). Values of all of these types can be assigned to a variable of type List<?> (which is where it differs from List<Object>!).
In general, you cannot add a string to such a list. However, you can read Object from the list and you can add null to it. You can also calculate the length of the list, etc. These are operations that are guaranteed to work for each of these types.
For a good introduction to wildcards, see the paper Adding Wildcards to the Java Programming Language. It is an academic paper, but still very accessible.
Java Generics : Wild Cards in Collections
extends
super
?
Today I am going to explain you how the wild cards are useful. To understand this concept is bit difficult
Now Suppose you have abstract class and in that you have abstract method called paintObject().
Now you want to use different type of collection in every child class.
This below is AbstractMain Method.
Here Steps we have taken for this Abstract Main method
1. We have created abstract class
2. In Parameter we have define T(you can use any character)
--In this case whichever class implement this method it can used any type of class.
ex. Class can implement method like
public void paintObject(ArrayList object) or public void paintObject(HashSet object)
3. And We have also used E extends MainColorTO
-- In this case E extends MainColorTo
-- It's clearly means whichever class you want to use that must be sub class of MainColorTo
4. We have define abstract method called paintObject(T object,E objectTO)
--Now here whichever class is implement method that method can use any class on first argument and second parameter that method has to use type of MainColorTO
public abstract class AbstractMain<T,E extends MainColorTO> {
public abstract void paintObject(T Object,E TO);
}
Now we will extend above abstract class and implement method on below class
ex.
public class MainColorTO {
public void paintColor(){
System.out.println("Paint Color........");
}
}
public class RedTO extends MainColorTO {
#Override
public void paintColor() {
System.out.println("RedTO......");
}
}
public class WhiteTO extends MainColorTO {
#Override
public void paintColor() {
System.out.println("White TO......");
}
}
Now we will take two example.
1.PaintHome.java
public class PaintHome extends AbstractMain<ArrayList, RedTO> {
#Override
public void paintObject(ArrayList arrayList,RedTO red) {
System.out.println(arrayList);
}
}
Now in above PaintHome.java you can check that we have used ArrayList in first argument(As we can take any class) and in second argument we have used RedTO(Which is extending MainColorTO)
2.PaintCar.java
public class PaintCar extends AbstractMain<HashSet, WhiteTO>{
#Override
public void paintObject(HashSet Object,WhiteTO white) {
System.out.println(Object);
}
}
Now in above PaintCar.java you can check that we have used HashSet in first argument(As We Can take any class) and in second argument we have used WhiteTO(Which is extending MainColorTO)
Ponint to Remember
You can not use super keyword at class level you can only use extends keyword at class level defination
public abstract class AbstractMain<P,E super MainColorTO> {
public abstract void paintObject(P Object,E TO);
}
Above code will give you compiler error.