How to specify method AnyObject<? super T, String> - java

I want to specify a method in an interface the signature of the method of an implementation (JPA 2 based) is:
List<T> getByStringValue(SingularAttribute<? super T, String> attribute, String value)
I want to specify this method in an interface (Object<? super T, String> is not possible) that abstracts from jpa. The implementing method could have a different signature but i want it to accept SingularAttribute<? super T, String> and i want to use it in type safe query without casting around.
At the end i want to specify all entity interaction in a "Repository" interface and want to give one JPA-based implementation that covers most of it for all entities (to minimize redundant code). I have finished it for CRUD-ops and getAll. Now i wish i could provide a generic approach for getByCriteria (one Critera is enough at the moment).

Java doesn't allow the non-generic-parameter part to itself be some kind of wildcard, eg any class that has certain generic parameters:
<T> void method(*<T, String> o) // can't do this
But you can define an abstract type and have all classes you want to use like this implement it, something like:
interface StringGetter<T> {
T getByStringValue(String value);
}
then:
public class WidgetStringGetter implements StringGetter<Widget> {
public Widget getByStringValue(String value) {
// whatever
}
}
and:
public static <T> T factory(StringGetter<T> getter, String value) {
return getter.getByStringValue(value);
}
finally:
Widget w = factory(new WidgetStringGetter(), "foo");

Try the following.
<R, T extends R> List<T> getByStringValue(SingularAttribute<R, String> attribute, String value)
The <R, T extends R> defines generic parameters for use in the method signature.

Related

How to encapsulate an unchecked cast to only allow unchecked generic type conversion?

I'm looking for a "proper" way to reduce the Java boilerplate involved in retrieving/modifying the generic type arguments at compile time. Usually, this boilerplate involves:
Using #SuppressWarnings("unchecked").
Spelling out explicitly the target generic type arguments.
Usually, creating an otherwise useless local variable just so that the supression can be applied to that staement only.
As a theoretical example, suppose I want to keep a map of Class to Supplier such that for each keyClass, its associated valueSupplier produces objects extending keyClass.
Edit 2: I changed the example from a map of Class to Class, to a map of Class to Supplier, because (the value) Class objects are special with respect to casts, and the original example had another solution not involving unchecked casts (thanks #Holger). Again, I'm only adding an example to illustrate the problem, I don't need to solve any particular example.
Edit 1: More precisely, a single SupplierMap object is populated say from a config file, and holds info such as "objects implementing interface I1 are provided by supplier S1", "I2 by S2", and so on. At runtime, we get calls such as I1 i1 = supplierMap.get(I1.class).get() which should produce an object with i1.getClass() == C1.class. I'm not interested in fixes/shortcuts, e.g. moving the cast to where it does not belong, such as having get() return Supplier<Object>. The cast belongs conceptually inside the SupplierMap. Also, I don't much care about this specific example, but about the general language problem.
With SupplierMap, I don't believe there is a way to capture the key-value generic parameter relation in Java so that the get() does not involve an unchecked compile-time cast. Concretely I could have:
class SupplierMap {
// no way to say in Java that keys and values are related
Map<Class<?>, Supplier<?>> map;
// can check the relation at compile time for put()
<T> void put(Class<T> keyClass, Supplier<? extends T> valueSupplier) {
map.put(keyClass, valueSupplier);
}
// but not for get()
<T> Supplier<? extends T> get(Class<T> keyClass) {
#SuppressWarnings("unchecked")
final Supplier<? extends T> castValueSupplier = (Supplier<? extends T>) map.get(keyClass);
return castValueSupplier;
}
}
As an alternative, one could have:
#SupressWarnings("unchecked")
<T> T uncheckedCast(Object o) {
return (T) o;
}
<T> Supplier<? extends T> get(Class<T> keyClass) {
return uncheckedCast(map.get(keyClass));
}
That looks much better, but the problem is that uncheckedCast is arguably too powerful: it can potentially cast anything into anything else at compile time (by hiding warnings). At runtime we'd still get CCE's, but that's not the point here. (The argument goes that ...) If one were to put this uncheckedCast into a library, the function could be abused to hide problems otherwise detectable at compile-time.
Is there a way to define such a similar unchecked cast function so that the compiler can enforce that it is only used to change generic type parameters?
I tried:
// error at T<U>: T does not have type parameters
<T, U> T<U> uncheckedCast(T t) {
return (T<U>) t;
}
also
<T, U extends T> U uncheckedCast(T t) {
return (U) t;
}
void test() {
Class<?> aClass = String.class;
// dumb thing to do, but illustrates cast error:
// type U has incompatible bounds: Class<capture of ?> and Class<Integer>
Class<Integer> iClass = uncheckedCast(aClass);
}
Edit: Have you seen this kind of an unchecked cast (even the all-powerful one above) in a common library? I looked in Commons Lang and Guava, but the only one I could find is Chronicle Core's ObjectUtils.convertTo(): there, passing eClass == null is equivalent to the all-powerful uncheckedCast, except that it also produces an undesired #Nullable (that is used by other branches).
You said
Also, I don't much care about this specific example, but about the general language problem.
but actually, this kind of problem should always be handled in relation to the actual problem you’re trying to solve. I’d go that far to say that this happens rarely enough, so a general utility method for doing unchecked casts regardless of the actual use case would not be justified.
Considering the SupplierMap, you said
I don't believe there is a way to capture the key-value generic parameter relation in Java so that the get() does not involve an unchecked compile-time cast.
That’s nailing the problem and pointing to the clean solution. You have to create a relationship between the key and value, e.g.
class SupplierMap {
static final class SupplierHolder<T> {
final Class<T> keyClass;
final Supplier<? extends T> valueSupplier;
SupplierHolder(Class<T> keyClass, Supplier<? extends T> valueSupplier) {
this.keyClass = keyClass;
this.valueSupplier = valueSupplier;
}
#SuppressWarnings("unchecked") // does check inside the method
<U> SupplierHolder<U> cast(Class<U> type) {
if(type != keyClass) throw new ClassCastException();
return (SupplierHolder<U>)this;
}
}
Map<Class<?>, SupplierHolder<?>> map = new HashMap<>();
<T> void put(Class<T> keyClass, Supplier<? extends T> valueSupplier) {
map.put(keyClass, new SupplierHolder<>(keyClass, valueSupplier));
}
<T> Supplier<? extends T> get(Class<T> keyClass) {
return map.get(keyClass).cast(keyClass).valueSupplier;
}
}
Here, the unchecked type cast is inside a method that performs an actual check allowing the reader to be confident about the correctness of the operation.
That’s a pattern that is actually used in real life code. Which hopefully addresses your question “Have you seen this kind of an unchecked cast (even the all-powerful one above) in a common library?”. I don’t think that any library uses a “do-entirely-unchecked” method, but rather, they have methods with a visibility as narrow as possible and likely tailored to the actual use case.
Yes, that means “boilerplate”. Which is not bad for an operation that the developer should really spend some seconds, before proceeding.
Note that this can be expanded to examples completely working without using Class as token:
interface SomeKey<T> {}
class SupplierMap {
static final class SupplierHolder<T> {
final SomeKey<T> keyClass;
final Supplier<? extends T> valueSupplier;
SupplierHolder(SomeKey<T> keyToken, Supplier<? extends T> valueSupplier) {
this.keyClass = keyToken;
this.valueSupplier = valueSupplier;
}
#SuppressWarnings("unchecked") // does check inside the method
<U> SupplierHolder<U> cast(SomeKey<U> type) {
if(type != keyClass) throw new ClassCastException();
return (SupplierHolder<U>)this;
}
}
Map<SomeKey<?>, SupplierHolder<?>> map = new HashMap<>();
<T> void put(SomeKey<T> keyClass, Supplier<? extends T> valueSupplier) {
map.put(keyClass, new SupplierHolder<>(keyClass, valueSupplier));
}
<T> Supplier<? extends T> get(SomeKey<T> keyClass) {
return map.get(keyClass).cast(keyClass).valueSupplier;
}
}
Which allows more than one key with the same type:
enum MyStringKeys implements SomeKey<String> {
SAY_HELLO, SAY_GOODBYE
}
public static void main(String[] args) {
SupplierMap m = new SupplierMap();
m.put(MyStringKeys.SAY_HELLO, () -> "Guten Tag");
m.put(MyStringKeys.SAY_GOODBYE, () -> "Auf Wiedersehen");
System.out.println(m.get(MyStringKeys.SAY_HELLO).get());
Supplier<? extends String> s = m.get(MyStringKeys.SAY_GOODBYE);
String str = s.get();
System.out.println(str);
}
The crucial part is that the now-unavoidable unchecked cast is still augmented with an actual check for the key validity. I’d never allow it without.
This doesn’t preclude scenarios where you really can’t check the correctness at all. But then, it is a good think that verbose artifacts like the #SuppressWarnings("unchecked") annotation indicate this right at the point where it is needed. A convenience method would only hide the problem, which is still there, even if we had a possibility to restrict its usage to generic types.
Answer to the previous revision of the question:
That’s actually easier than you think:
class ImplMap {
Map<Class<?>, Class<?>> map;
<T> void put(Class<T> keyClass, Class<? extends T> valueClass) {
map.put(keyClass, valueClass);
}
<T> Class<? extends T> get(Class<T> keyClass) {
final Class<?> implClass = map.get(keyClass);
return implClass.asSubclass(keyClass);
}
}
This is not an unchecked operation, as the method asSubclass really checks whether the implClass class is a subclass of keyClass. Assuming that the map has been populated via the put method only, without any unchecked operations, this test will never fail.
The only thing that differs, is the treatment of null, e.g. when the key was not present in the map. Unlike a cast, this would throw an exception, as it is a method invocation.
So if calling this method with absent keys is allowed and should result in null, it must be handled explicitly:
<T> Class<? extends T> get(Class<T> keyClass) {
final Class<?> implClass = map.get(keyClass);
return implClass == null? null: implClass.asSubclass(keyClass);
}
Note that likewise, the method
#SupressWarnings("unchecked")
<T> T uncheckedCast(Object o) {
return (T) o;
}
is unnecessary if you have the Class object, as then, you can invoke cast on it.
E.g., the following would be a valid addition to your ImplMap class:
<T> T getInstance(Class<T> keyClass) {
try {
return keyClass.cast(map.get(keyClass).getConstructor().newInstance());
} catch (ReflectiveOperationException ex) {
throw new IllegalStateException(ex);
}
}
As an additional note, registering interface implementation via configuration files sounds like you should have a look at the ServiceLoader API and the underlying mechanisms. See also the Creating Extensible Applications chapter of the Java tutorial.
Why don't you try something like this, instead of declaring the types individually for functions, make the class generic and class handles this T types of Class instances.
class ImplMap<T> {
// Values are already related here
Map<Class<T>, Class<? extends T>> map;
// Already compiler aware of the type.
void put(Class<T> keyClass, Class<? extends T> valueClass) {
map.put(keyClass, valueClass);
}
// Compiler already aware of the type just like with 'put'.
Class<? extends T> get(Class<T> keyClass) {
return map.get(keyClass);
}
}
This doesn't involve unchecked cast since the type relationship already defined with the Map declaration and no need to SuppressWarning (Compiler doesn't warn).
Although compiler would warn about unchecked call when invoke the put and get function if you don't define type on ImplMap object creation as it not takes a type at all and if you define a type, you can put that type of keys only into that map which duplicates.

Generically typed visitor getting called on wrong types

I am using a generic abstract class of a framework AbstractProcessor<T extends CtElement> which is basically a visitor that visits all elements T. There is a method
public void process(T element)
that acts upon all elements of the specified type and does something.
I then have concrete class implementations of this AbstractProcessor that I create using some sort of factory pattern, while holding a list of the common supertype AbstractProcessor to then call the process-method via polymorphism on them. One of these concrete classes might be smth like XYZProcessor<T extends CtElement> extends AbstractProcessor<T>.
I now create these concrete processors like new XYZProcessor<CtNamedElement>() where CtNamedElement is a subtype of CtElement, so the process-method of the XYZProcessor only gets called with CTNamedElements. But the process-method seems to get called for all visisted elements of type CtElement, NOT only for those of the type CtNamedElement as I want to.
Does anyone know what is happening here?
EDIT: relevant code:
creating processors like this
case CLASS:
//CtClass is subtype of CtNamedElement
this.setProcessor(new AnnotatedWithProcessor<CtClass>(targetName, attributeMappings, metapackage));
break;
Class definition:
public class AnnotatedWithProcessor<T extends CtNamedElement> extends AbstractProcessor<T> {
#Override
public void process(T element) {
//do stuff here with elements of correct type
}
And then calling the processors like this:
//this gets set with a concrete case like above
AbstractProcessor<?> processor;
...
//this astModel gets processed with the respective processor,
//where I expect the process method only getting called for the correct types (in this case only when coming over elements of type CtClass),
//but the method gets called for all types of CtNamedElement, not only for those of type CtClass
this.astModel.processWith(processor);
Seems like you're doing so illegal casting somewhere, but it's hard to tell without seeing more of your implementation. Who is calling XYZProcessor::process? Why do you expect defining a generic interface to perform any sort of filtering?
Going to take a shot in the dark here, but it seems like what you probably want is a lookup map for types versus processors. This kind of code can get messy, so it's a good idea to limit access to this mapping using well tested methods:
private final Map<Class, Object> processorMap = new HashMap<Class, Object>();
public <T extends CtElement> void putProcessor(
Class<T> elementClass,
AbstractProcessor<? extends T> processor
) {
processorMap.put(elementClass, processor);
}
#SuppressWarnings("unchecked")
public <T extends CtElement> AbstractProcessor<? extends T> getProcessor(
Class<T> elementClass,
) {
return (AbstractProcessor<? extends T>) processorMap.get(elementClass);
}
Now when you search for a processor, you can use this map to find the correct implementation to call:
public void <T extends CtElement> process(T element) {
getProcessor(element.getClass()).process(element);
}
You may want to extend this to allow multiple implementations for each class, or filter the processorMap for all valid processors for element.getClass() using Class::isInstance and then processing for each valid key.

Ensure different types of generics

I am trying to create a generic converter interface, which will convert T objects to U objects by using the same method name, i.e. convert:
public interface GenericConverter<T, U> {
T convert(U fromObject);
U convert(T fromObject);
}
Of course, generics erasure tranforms both methods into the following during compilation:
convert(object fromObject);
So both methods have the same erasure, which results in an error during compilation.
In my example it is logical that I will always use different object types for T and U. Is there a way to keep the same method name (convert), be able to encapsulate the fact that T and U are different types and ensure that the proper method will be called in each case?
Unless the two types T and U are based in two separate type hierarchies (i.e. each one will always have some distinct superclass), there's no way of having the two methods with same name. It doesn't even make sense semantically in that case - what should be the semantic difference between the two methods if you cannot distinguish the two types in any reasonable matter?
Apart of the suggested renaming of the methods, consider also only having one such method in the interface and instead using a GenericConverter<T, U> and GenericConverter<U, T> wherever you need to transform both ways.
It's not directly possible due to type erasure. Several options have already been listed in the other answers. One of them implicitly aimed at separating the conversions. So instead of having a single converter, you could have two distinct ones:
public interface GenericConverter<T, U> {
U convert(T fromObject);
}
GenericConverter<Integer, String> forward = Converters.integerString();
GenericConverter<String, Integer> backward = Converters.stringInteger();
But note that the GenericConverter interface in this cases is structurally equal to the Function interface - so there is probably no reason to create a new one.
Instead, if you want to have this "forward and backward converter" as some sort of a named entity (with both conversion functions inseparably linked together), you could define an interface for that:
public interface GenericConverter<T, U> {
Function<T, U> forward();
Function<U, T> backward();
}
This could be used as follows:
GenericConverter<Integer, String> converter = Converters.integerString();
String string = converter.forward().apply(someInteger);
Integer integer = converter.backward().apply(someString);
Whether or not this is the "best" solution here depends on the intended usage patterns. One advantage could be that, with a generic (!) utility function like this...
private static GenericConverter<T, U> create(
Function<T, U> forward, Function<U, T> backward) {
return new GenericConverter() {
#Override
public Function<T, U> forward() {
return forward;
}
#Override
public Function<U, T> backward() {
return backward;
}
}
}
creating a new converter would be easy as pie:
public static GenericConverter<Integer, String> integerString() {
return create(
integer -> String.valueOf(integer),
string -> Integer.parseInt(string)
);
}
Problem
When you say,
it is logical that I will always use different object types for T and U
Compiler does not know. Types can be forced to be same, but not to be different (without constraints).
Approach 1
class ConversionSource {}
class ConversionTarget {}
interface GenericConverter<T extends ConversionSource, U extends ConversionTarget> {
T convert(U obj);
U convert(T obj);
}
Now, erasures are different. You get the behavior you want with source you want, but usage is severely restricted because of constraints.
Approach 2
interface InvertibleConverter<T, U> {
U convert(T obj);
InvertibleConverter<U, T> inverse();
}
class Tokenizer implements InvertibleConverter<String, Stream<String>> {
#Override
Stream<String> convert(String obj) {
return Arrays.stream(obj.split(" "));
}
#Override
InvertibleConverter<Stream<String>, String> inverse() {
return new InvertibleConverter<Stream<String>, String>() {
#Override
public String convert(Stream<String> obj) {
return obj.collect(Collectors.joining(" "));
}
#Override
public InvertibleConverter<String, Stream<String>> inverse() {
return Tokenizer.this;
}
};
}
}
Usage can be as follows
InvertibleConverter<String, Stream<String>> splitter = new Tokenizer();
String sentence = "This is a sentence";
Stream<String> words = splitter.convert(sentence);
String sameSentence = splitter.inverse().convert(words);
This approach works even when T and U are identical.
Hope this helps.
Good luck

TreeMap with Classes as Key

I am trying to program a kind of registry for objects of different classes.
I have the following:
public interface DbObject{
void setId(long id);
Long getId();
}
A prototypic class implementing this interface would be the following:
public class BasicDbObject implements DbObject{
private long id=null;
void setId(long id){
this.id=id;
}
Long getId(){
return id;
}
}
I want to build various different Implementations of this Interface.
And I want to be able to have a Map object, that maps from each implementing class to a Map of instances.
Something like this:
Map <Class<C implements DbObject> , Map<Long, C>> registry = new TreeMap/HashMap/SomeOtherKindOfMap (...)
I know I could do something like
Map <String,Map<Long,DbObjects>> registry = new ...
But this way I would have to write some more code for determining names, comparing classes and so on. Is there an easier way to accomplish this?
So what I want to know: is it possible to have class objects as keys in a tree map?
What would be the syntax to declare a map object, that maps from implementing classes C to a map objects each mapping from a long object (the id) to instances of C?
I want to be able to do requests like the following:
BasicObject bo = registry.get(BasicObject.class).get(42);
assuing id did
BasicObject bo=new BasicObject(...);
innerMap = new SomeMap<Long,BasicObject>();
innerMap.put(42,bo);
registry.put(BasicObject.class,innerMap);
before.
Please tell me, if this still is not clear, I have difficulties to explain, since english is not my mother tongue.
Thank you in advance.
Edit:
It turns out, i can do something very close to what I want, when defining a generic class around the map:
public class ObjectRegistry <T extends DbObject>{
private HashMap<Class<T>, TreeMap<Long,T>> registry=null;
ObjectRegistry(){
registry=new HashMap<Class<T>, TreeMap<Long,T>>();
}
public void register(T dbObject){
TreeMap<Long, T> map = registry.get(dbObject.getClass());
if (map==null){
map=new TreeMap<Long,T>();
registry.put((Class<T>) dbObject.getClass(),map);
}
map.put(dbObject.getId(),dbObject);
}
public <T extends DbObject>T get(Class<T> objectClass,long id){
TreeMap<Long, T> map = (TreeMap<Long, T>) registry.get(objectClass);
if (map != null){
return map.get(id);
}
return null;
}
public TreeMap<Long,T> getAll(Class<T> dbObjectClass) {
return registry.get(dbObjectClass);
}
}
I use a TreeMap for the inner mappings since I want to easily return Class instances sorted by id.
So the refined question is:
Is there a way to do this, without the <T extends DbObject> clause in the Class head?
Edit 2:
Thinking through it again, it turns out that John's answer is exactly the solution to this.
Here is my final code:
HashMap<Class<? extends DbObject>, TreeMap<Long, ? extends DbObject>> registry = null;
public <T extends DbObject> T get(Class<T> clazz, long id) {
TreeMap<Long, T> map = (TreeMap<Long, T>) registry.get(clazz);
if (map != null) {
return map.get(id);
}
return null;
}
public <T extends DbObject> void register(T dbObject) {
TreeMap<Long, T> map = (TreeMap<Long, T>) registry.get(dbObject.getClass());
if (map == null) {
map = new TreeMap<Long, T>();
registry.put((Class<T>) dbObject.getClass(), map);
}
map.put(dbObject.getId(), dbObject);
}
public <T extends DbObject> TreeMap<Long, T> getAll(Class<T> dbObjectClass) {
return (TreeMap<Long, T>) registry.get(dbObjectClass);
}
It does not need the <T extends DbObject> clause in the Class head.
So what I want to know: is it possible to have class objects as keys in a tree map?
TreeMap depends on there being a total order over the key space, as established by the key type having a natural order (by implementing Comparable) or by a separate Comparator object that you provide. Classes do not have a natural order. It is conceivable that you could write a suitable Comparator, but that seems very contrived to me.
But why do you specifically need a TreeMap? You didn't describe any requirement that would not be at least as well addressed by any other kind of Map. In particular, I almost always find HashMap to be a better choice, and I don't see any reason why it would be unsuitable in this one. It can certainly have objects of type Class as keys.
Moreover, if indeed you don't need any particular implementation, then you are best off declaring the type simply as a Map. That way you can actually provide any Map implementation, and even change which one you do provide if you ever discover a reason to do so.
What would be the syntax to declare a map object, that maps from implementing classes C to a map objects each mapping from a long object (the id) to instances of C?
You ask that the constraints on the type of each value be dependent on the type of the associated key, but there is no way to declare a type that enforces such a relationship. Whether a particular key or a particular value is appropriate for the Map is a function of the type of the map alone, not of each others' type.
You can write generic methods around access to your map that provide the appearance of what you want, but the data retrieval methods will need to cast. For example:
Map<Class<? extends DbObject>, Map<Long, ? extends DbObject>> registry = /*...*/;
<T extends DbObject> Map<Long, T> getRegistryMap(Class<T> clazz) {
return (Map<Long, T>) registry.get(clazz);
}
<T extends DbObject> T get(Class<T> clazz, Long id) {
Map<Long, T> map = getRegistryMap(clazz);
return (map == null) ? null : map.get(id);
}
<T extends DbObject> T put(Class<T> clazz, Long id, T obj) {
Map<Long, T> map = getRegistryMap(clazz);
if (map == null) {
map = new HashMap<>();
registry.put(clazz, map);
}
return map.put(id, obj);
}
Updated to add:
So the refined question is: Is there a way to do this, without the <T extends DbObject> clause in the Class head?
Yes, what I already wrote. Just slap a plain class declaration around it. You do not need a generic class to have generic methods. In fact, the two are orthogonal. Regular methods of a generic class can use that class's type parameters. That does not make them generic methods. A method is generic if it declares its own type parameter(s), as mine above do. Your get() method also does that, and it is important to understand that the type parameter <T> you declare explicitly in the method signature shadows the class's type parameter of the same name: it is a different T.

How do I use Realm with generic type?

I have a generic method and would like to retrieve objects using the generic type. This is my method:
public static <T extends RealmObject & IndentifierModel> void storeNewData() {
...
T item = realm.where(Class<T>) // Not compiling (Expression not expected)
.equalTo("ID", data.get(i).getID())
.findFirst();
}
The above isn't working for realm.where(Class<T>). How do I pass in my generic type to Realm?
You have to supply the generic parameter like so:
public static <T extends RealmObject & IndentifierModel> void storeNewData(Class<T> clazz) {
T item = realm.where(clazz)
.equalTo("ID", 123)
.findFirst();
}
Class<T> is not valid, since that's like saying realm.where(Class<List<String>>) or realm.where(Class<String>). What you need is an actual Class<T> instance. But you cannot use T.class either since T is not available at runtime due to type-erasure. At runtime, the method basically needs a Class<T> instance to work properly. Since you cannot get that from T, you will have to explicitly supply an argument of type Class<T>.

Categories

Resources