Avoid cast in a generics hierarchy - java

I have some difficulty to simplify more the problem. Sorry if they are too many code here.
I try to improve the architecture of the code above because I hate warning and cast and I feel something wrong.
Now, the code.
I have a util class with these two parametrized methods (same signature as OpenJPA's CriteriaBuilder...)
public class MyUtil {
public void equal(List<?> l, Object value) {
// do something (see CriteriaBuilder.equal method)
}
public <Y extends Comparable<? super Y>> void greaterThan(List<? extends Y> l, Y value) {
// do something (see CriteriaBuilder.greaterThan method)
}
}
Then, I want to be able to abstract them to call it via an interface.
public interface IOperation<T> {
// maybe make this method generic ? but how ?
public abstract void doOp(List<T> l, T value);
}
public abstract class AbstractOperation<T> implements IOperation<T> {
protected MyUtil myUtil;
}
public class EqualOp extends AbstractOperation<Object> {
#Override
public void doOp(List<Object> path, Object value) {
myUtil.equal(path, value);
}
}
public class GreaterThanOp<T extends Comparable<? super T>> extends AbstractOperation<T> {
#Override
public void doOp(List<T> path, T value) {
myUtil.greaterThan(path, value);
}
}
I create a factory
public class OperationFactory {
private static OperationFactory instance;
public static OperationFactory getInstance() {...}
public IOperation<?> get(String op) {
if ("=".equals(op)) {
return new EqualOp();
} else if (">".equals(op)) {
return new GreaterThanOp<Comparable<? super Object>>();
}
throw new InvalidParameterException();
}
}
Then I use it :
public class Client {
public void needOp(String op) {
IOperation<String> operation = (IOperation<String>) OperationFactory.getInstance().get(op); // How to avoid this cast ?
List<String> l = null;
operation.doOp(l, "a string");
}
}
My question is : is it possible to avoid this cast in the Client class ? How ? Is there a way to have a better architecture ?
Thanks for reading

I'm assuming you can require your type to be Comparable.
Parameterize EqualOp like GreaterThanOp:
public class EqualOp<T extends Comparable<T>> extends AbstractOperation<T> {
#Override public void doOp(List<T> path, T value) ...
And define get() like this:
public <T extends Comparable<T>> IOperation<T> get(String op) {
if ("=".equals(op)) {
return new EqualOp<T>();
} else if (">".equals(op)) {
return new GreaterThanOp<T>();
}
...

Related

I don't understand why my generic type declaration doesn't match

Here are the classes declarations:
public interface IPoint<N extends Number> {
...
}
public abstract class PointP<N extends Number> implements IPoint<N> {
...
}
public class Pointf extends PointP<Float> {
...
}
public interface ISegment<T extends Number, P extends IPoint<T>> {
...
}
public abstract class SegmentP<N extends Number, P extends IPoint<N>> implements ISegment<N, P> {
...
}
public class Segmentf extends SegmentP<Float, Pointf> {
...
}
public abstract class LinesPIterator<N extends Number, S extends ISegment<N, IPoint<N>>> implements Iterable<S>, Iterator<S> {
...
}
public class LinesfIterator extends LinesPIterator<Float, Segmentf> {
...
}
The compiler refuses the Segmentf type in the generic declaration of the LinesfIterator class with the error message:
Bound mismatch: The type Segmentf is not a valid substitute for the bounded parameter <S extends ISegment<N,IPoint<N>>> of the type LinesPIterator<N,S>
However for me everything seems correct. The declaration of the LinesfIterator class seems to me to have the same hierarchical schema as the Segmentf class which compiles without problem.
Is there a solution to this way of doing things?
As already said, your hierarchy seems to be unnecessarily complex and shall be simplified. For example, I see no meaning in Pointf -> PointP -> IPoint the hierarchy.
If you want to fix your issue, you have to allow a subtype ? extends IPoint<N> in the LinesPIterator class, so:
public abstract class LinesPIterator<N extends Number, S extends ISegment<N, ? extends IPoint<N>>>
implements Iterable<S>, Iterator<S>
{
// ...
}
Moreover, there would be better to implement only Iterable as long as it provides an Iterator and you might end up with duplicated implementation.
public static class LinesfIterator extends LinesPIterator<Segmentf, Pointf, Float> {
#Override
public Iterator<Segmentf> iterator() {
return new Iterator<Segmentf>() {
#Override
public boolean hasNext() { /* TO DO */ }
#Override
public Segmentf next() { /* TO DO */ }
};
}
}
This remark on the use of an anonymous class rather than a direct use really caught my attention because intuitively, when I can avoid going through an anonymous class I do. On the one hand because it is an additional instantiation and on the other hand because it is more difficult to identify at debug (when they are several in the same class).
And I can't see the reasons why I should prefer the use of an anonymous class for this case.
Maybe with my classes as an example the explanation will be easier.
for(Segmentf segment : new LinesfIterator(cube.getPoints(), cube.getIndices())) {
System.out.println(segment);
}
public abstract class LinesPIterator<N extends Number, S extends ISegment<N, ? extends IPoint<N>>> implements Iterable<S>, Iterator<S> {
private N[][] points;
private int[] indices;
private int count;
public LinesPIterator(N[][] points, int[] indices) {
super();
this.points = points;
this.indices = indices;
}
protected abstract S instanciateIteration(final N[] pointDeb, final N[] pointFin);
#Override
public Iterator<S> iterator() {
return this;
}
#Override
public boolean hasNext() {
return count < (indices.length - 1);
}
#Override
public S next() {
return instanciateIteration(points[indices[count++]], points[indices[count++]]);
}
}
public class LinesfIterator extends LinesPIterator<Float, Segmentf> {
public LinesfIterator(Float[][] points, int[] indices) {
super(points, indices);
}
#Override
protected Segmentf instanciateIteration(Float[] point1, Float[] point2) {
return new Segmentf(point1, point2);
}
}

How to deliver the class of a generic type to a method in Java?

I want to implement a class that instantiates generic types.
public class DisjointSet<T extends Set<E>, E> {
private final Class<T> setType;
public DisjointSet(Class<T> setClass) {
this.setType = setClass;
}
public void doSomething(E Element) {
T set = setClass.newInstance();
set.add(element);
}
}
I tried instantiating the class like this:
DisjointSet<HashSet<Integer>, Integer> disjointSet = new DisjointSet<>(HashSet<Integer>.class);
However using .class on a generic type does not seem to be allowed. How would I correctly pass the required Class of a generic type to the constructor?
Not sure it is good to expose the inner set type (Hash versus other) in the parameterized type.
Actually due to type erasure you can't instantiate parameterised types directly, but you can pass in a factory,
package langGenerics;
import java.util.HashSet;
import java.util.Set;
public class UseGenerics {
public static void main(String[] args) {
SetFactory<Integer> setFactory = HashSet::new;
DisjointSet<Integer> disjointSet = new DisjointSet<>(setFactory);
disjointSet.doSomething( 123 );
}
}
interface SetFactory<T> { Set<T> get(); }
class DisjointSet<T> {
private SetFactory<T> setFactory;
public DisjointSet(SetFactory<T> setFactory) {
this.setFactory = setFactory;
}
public void doSomething(T item) {
Set<T> set = setFactory.get();
set.add(item);
}
}
If you really want to init your own set storage, then I suggest you to pass Supplier to your constructor:
public static class DisjointSet<T extends Set<E>, E> {
T set;
public DisjointSet(Supplier<T> supplier) {
set = supplier.get();
}
public void doSomething(E element) {
set.add(element);
}
}
Then use it:
DisjointSet<HashSet<Integer>, Integer> set = new DisjointSet<>(HashSet::new);
if this is what you wanted,
public class DisjointSet<T extends Set<E>, E> {
private final Class<T> setType;
public DisjointSet(Class<T> setClass) {
this.setType = setClass;
}
public static void main(String[] args) {
DisjointSet<HashSet<Integer>, Integer> disjointSet = new DisjointSet(new HashSet<Integer>().getClass());
}
}

Java method returning two or more generic types

There are a lot of questions regarding Java methods returning generic types, but none of them helped me out so far.
So here's my code:
interface DAO<K, T> {
void insert(T t);
void update(K k, T t);
void delete(K k);
void delete();
T select(K k);
List<T> select();
}
public class CourseDAO implements DAO<String, Course> {
public void insert(Course t) {}
public void update(String k, Course t) {}
public void delete(String k) {}
public void delete() {}
public Course select(String k) {}
public List<Course> select() {}
}
public class StudentDAO implements DAO<Long, Student> {
public void insert(Student t) {}
public void update(Long k, Student t) {}
public void delete(Long k) {}
public void delete() {}
public Student select(Long k) {}
public List<Student> select() {}
}
public enum EntityType { COURSE, STUDENT }
Now I want a factory method which accepts an EntityType parameter and return an instance of CourseDAO or StudentDAO depending on the parameter value.
I tried the code below without success:
public <K,T> DAO<K,T> createDAOFactory(EntityType type) {
switch (type) {
case COURSE : return (K,T) new CourseDAO(); break;
case STUDENT : return (K,T) new StudentDAO(); break;
}
return null;
}
Could anyone help me in writing and invoking this method???
Cheers,
Romualdo.
The cast you're looking for is (DAO<K,T>). But you'll get a warning because generic type erasure makes it unsafe. Another inherent risk in the switch factory is that you might forget to create a corresponding case when you add a new EntityType. A safer alternative would be to redefine EntityType with generic types, and let it be the factory. Unfortunately, this isn't possible with proper enums, but you can simulate it like this:
abstract class EntityType<K, T> {
public abstract DAO<K, T> createDAO();
public static final EntityType<String, Course> COURSE = new EntityType<String, Course>() {
#Override
public DAO<String, Course> createDAO() {
return new CourseDAO();
}
};
public static final EntityType<Long, Student> STUDENT = new EntityType<Long, Student>() {
#Override
public DAO<Long, Student> createDAO() {
return new StudentDAO();
}
};
}
Or you can use lambdas to reduce the boilerplate:
class EntityType<K, T> {
private final Supplier<DAO<K, T>> constructor;
private EntityType(Supplier<DAO<K, T>> constructor) {
this.constructor = constructor;
}
public DAO<K, T> createDAO() {
return constructor.get();
}
public static final EntityType<String, Course> COURSE = new EntityType<>(CourseDAO::new);
public static final EntityType<Long, Student> STUDENT = new EntityType<>(StudentDAO::new);
}
Now, instead of calling createDAOFactory(EntityType.COURSE), you would just call EntityType.COURSE.createDAO().
maybe you can do like this?
public class StudentDAO<Long,Student> implements DAO<Long, Student> {
public void insert(Student t) {}
public void update(Long k, Student t) {}
public void delete(Long k) {}
public void delete() {}
public Student select(Long k) {return null;}
public List<Student> select() {return null;}
}
public <K,T> DAO<K,T>createDAOFactory(EntityType type) {
switch (type) {
case COURSE : return new CourseDAO();
case STUDENT : return new StudentDAO();
}
return null;
}
first answer
you do not need use generics,because Implementation class has specified the type.
public DAO createDAOFactory(EntityType type) {
switch (type) {
case COURSE : return new CourseDAO();
case STUDENT : return new StudentDAO();
}
return null;
}

Java: Working with Generics and Maps without Casting / #SuppressWarnings

I now came several times across this problem and always kinda solved this with some casts and #SuppressWarnings annotations.
The relevant interfaces / abstract classes:
public abstract class Data { }
public interface DataOperations {
boolean isValid();
}
public interface DataOperationsFactory<T extends Data> {
Class<T> getDataClass();
DataOperations getOperations(T data);
}
Example Implementations:
public class DataImpl1 extends Data {
public String foo;
}
public class DataImpl1Operations implements DataOperations {
private DataImpl1 data;
public DataImpl1Operations(DataImpl1 data) {
this.data = data;
}
public boolean isValid() {
return data.foo != null;
}
}
public class DataImpl1OperationsFactory extends DataOperationsFactory<DataImpl1> {
public Class<DataImpl1> getDataClass() {
return DataImpl1.class;
}
DataOperations getOperations(DataImpl1 data) {
return new DataImpl1Operations(data);
}
}
Using this pattern, I can decide whether I need to create a new DataImpl1Operations everytime. Or maybe use a final static NO_OP implementation or what have you.
The Code:
Now I'd like to put all those factories inside a Map<Class<T>, DataOperationsFactory<T>> (constructor). And afterwards read from it (getOps method).
public class Test {
Map<Class<?>, DataOperationsFactory<?>> map;
public Test(List<DataOperationsFactory<?>> fs) {
for(DataOperationsFactory<?> f : fs) {
map.put(f.getDataClass(), f);
}
}
#SuppressWarnings("unchecked")
public <T extends Data> DataOperations getOps(T data) {
// --> Here I need to do an unchecked cast <--
DataOperationsFactory<? super T> f =
(DataOperationsFactory<? super T>) map.get(data.getClass());
return f.getOperations(data);
}
}
Is there any way doing this without unchecked casting?
You can delegate to a private method that captures the type, so it can be used to reliably cast to the correct Data subclass:
Map<Class<?>, DataOperationsFactory<?>> map;
// Unchanged
public Test(List<DataOperationsFactory<?>> fs) {
for(DataOperationsFactory<?> f : fs) {
map.put(f.getDataClass(), f);
}
}
public DataOperations getOps(Data data) {
DataOperationsFactory<?> f = map.get(data.getClass());
return getOperations(f, data);
}
private static <T extends Data> DataOperations getOperations(DataOperationsFactory<T> f,
Data data) {
return f.getOperations(f.getDataClass().cast(data));
}

type parameter extends and method parameter mismatch error

I created something like below:
ConcreteObserver1 is the subclass of IObserver
Interfaces definitions:
public interface ISubject<T,O extends IObserver<T>> {
public void addObserver(O observer);
public void removeObserver(O observer);
public void updateAllSubjects(T value);
}
public interface IObserver<T> {
public void update(T value);
}
public class ConcreteObserver1<T> implements IObserver<T> {
Concrete Subject class containing IObserver
public class ConcreteSubject<T, O extends IObserver<T>> implements
ISubject<T,O> {
public ConcreteSubject() {
addObserver(new ConcreteObserver1<T>());
}
ConcurrentSkipListSet<O> observersList = new ConcurrentSkipListSet<O>();
public void addObserver(O observer) {
observersList.add(observer);
addObserver(new ConcreteObserver1<T>()); not working.
It complains as below
The method addObserver(O) in the type ConcreteSubject is not applicable for the arguments (ConcreteObserver1)
Why ?
I told O extends IObserver<T> in ConcreteSubject type parameter definition, which says O is a sub-type of IObserver which is ConcreteObserver1
Why it is complaining.
The type parameter O is defined to be a subtype of IObserver<T>, this is correct. But it may stand for any subtype. You don't say anywhere that it stands for ConcreteObserver1. It could also stand for ConcreteObserver42 or something else.
From what you posted so far, it does not seem like you really have to define O as a type parameter of ConcreteSubject. You could specifically say that ConcreteSubject always uses a ConcreteObserver1. If this is not the case, you should probably explain your intention more clearly (and possibly, in a more readable form).
(Edited based on the comments)
interface ISubject<T,O extends IObserver<T>>
{
void addObserver(O observer);
void removeObserver(O observer);
void updateAllSubjects(T value);
}
interface IObserver<T>
{
void update(T value);
}
class ConcreteObserver1<T> implements IObserver<T>
{
#Override
public void update(T value) {}
}
class ConcreteObserver2<T> implements IObserver<T>
{
#Override
public void update(T value) {}
}
class ConcreteObserver3<T> implements IObserver<T>
{
#Override
public void update(T value) {}
}
class ConcreteSubject<T> implements ISubject<T,IObserver<T>>
{
ConcurrentSkipListSet<IObserver<T>> observersList =
new ConcurrentSkipListSet<IObserver<T>>();
public ConcreteSubject()
{
addObserver(new ConcreteObserver1<T>());
addObserver(new ConcreteObserver2<T>());
addObserver(new ConcreteObserver3<T>());
}
#Override
public void addObserver(IObserver<T> observer)
{
observersList.add(observer);
}
#Override
public void removeObserver(IObserver<T> observer)
{
observersList.remove(observer);
}
#Override
public void updateAllSubjects(T value)
{
for (IObserver<T> observer : observersList)
{
observer.update(value);
}
}
}

Categories

Resources