I'm using Hibernate validator and trying to create a little util class:
public class DataRecordValidator<T> {
public void validate(Class<T> clazz, T validateMe) {
ClassValidator<T> validator = new ClassValidator<T>(clazz);
InvalidValue[] errors = validator.getInvalidValues(validateMe);
[...]
}
}
Question is, why do I need to supply the Class<T> clazz parameter when executing new ClassValidator<T>(clazz)? Why can't you specify:
T as in ClassValidator<T>(T)?
validateMe.getClass() as in ClassValidator<T>(validateMe.getClass())
I get errors when I try to do both options.
Edit: I understand why #1 doesn't work. But I don't get why #2 doesn't work. I currently get this error with #2:
cannot find symbol
symbol : constructor ClassValidator(java.lang.Class<capture#279 of ? extends java.lang.Object>)
location: class org.hibernate.validator.ClassValidator<T>
Note: Hibernate API method is (here)
Because T is not a value - it's just a hint for the compiler. The JVM has no clue of the T. You can use generics only as a type for the purposes of type checking at compile time.
If the validate method is yours, then you can safely skip the Class atribute.
public void validate(T validateMe) {
ClassValidator<T> validator =
new ClassValidator<T>((Class<T>) validateMe.getClass());
...
}
But the ClassValidator constructor requires a Class argument.
Using an unsafe cast is not preferred, but in this case it is actually safe if you don't have something like this:
class A {..}
class B extends A {..}
new DataRecordValidator<A>.validate(new B());
If you think you will need to do something like that, include the Class argument in the method. Otherwise you may be getting ClassCastException at runtime, but this is easily debuggable, although it's not quite the idea behind generics.
Because ClassValidator is requiring a Class object as its parameter, NOT an instance of the class in question. Bear in mind you might be able to do what you're trying to do with this code:
ClassValidator<? extends T> validator = new ClassValidator<? extends T>(validateMe.getClass());
Related
I have an interface Persistable which looks like this, the <T extends Statement<T>> List<Statement<T>> is to allow it to support both BoundedStatements and SimpleStatements in data stax 4.x driver.
public interface Persistable {
<T extends Statement<T>> List<Statement<T>> statements();
}
This java interface is inherited by Kotlin class A such that
data class UpdateRule(
private val something: S) : Persistable {
override fun statements(): List<Statement<BoundStatement> {
return PutKeyValue(Function(orgId, serviceId), JsonUtil.toJson(rule)).statements() //this returns BoundStatement
}
}
However, this gives the error Conflicting overloads.This code seems to work in Java(although with a warning), but in Kotlin it does not allow at all, how can I resolve this while also making sure parent interface remains generic to both Bound and Simple Statement?
You seem to misunderstand what the generics in Persistable mean. As it is written right now, you are supposed to implement the statements method so that it can handle any kind of T that extends Statement<T>. The generics there doesn't mean "implement this by choosing a kind of statement that you like".
It only produces a warning in Java because Java's generics is broken. Because of type erasure, List<Statement<BoundStatement> and List<Statement<T>> both erase to the same type - List, so the method in UpdateRule does implement the method in the interface if you consider the erasures. OTOH, type erasure isn't a thing in Kotlin (at least not in Kotlin/Core).
To fix this, you can move the generic type parameter to the interface:
public interface Persistable<T extends Statement<T>> {
List<Statement<T>> statements();
}
data class UpdateRule(private val something: S) :
Persistable<BoundStatement> {
override fun statements(): List<BoundStatement> =
PutKeyValue(Function(orgId, serviceId), JsonUtil.toJson(rule)).statements()
}
Notice how when we are implementing the interface, we can now specify the specific T that we are implementing for.
In Java just like in Kotin, the value of the type parameter of a generic method is determined by the caller of the method, and can be different at every call of the method, even on the same instance.
In your specific case, with the Java interface declared like this, statements() is supposed to be implemented in such a way that the caller can choose which type of statement will be returned by a given call to this method. This is not the case in your implementation, and that's why Kotlin doesn't allow it. As pointed out by #Sweeper, Java is broken in this respect and might let you get away with a warning.
This is different when using a generic class or interface. If you define the type parameter at the class/interface level, then the value of that type parameter is determined at construction time of the class, or can be fixed by subclasses. For a given instance, all calls to the method will return a well known type, which is (I believe) what you want here.
You can do this in Java:
public interface Persistable<T extends Statement<T>> {
List<Statement<T>> statements();
}
And then in Kotlin:
data class UpdateRule(
private val something: S
) : Persistable<BoundStatement> {
override fun statements(): List<BoundStatement> {
return PutKeyValue(Function(orgId, serviceId), JsonUtil.toJson(rule)).statements() //this returns BoundStatement
}
}
I am currently automating a process of a data handler. What I mean with automating is that the DataHandlers are initiated automatically via reflection based on a specific configuration.
But I am on a point where I do not know how I should solve this problem. It is about this peace of code:
Class<?> clazz = classLoader.loadClass(d);
Object values = clazz.getMethod("values").invoke(null);
RSA.addDataHandler(clazz,new DataHandlerSetAdapter<>(values));
I am loading the class via the classLoader and invoking a static method called "values" which returned a bunch of, you have suggested right, values!
Now the problem is with new DataHandlerSetAdapter<>(values)) which has an error in <> because the Object does not know which class to initiate.
Cannot infer arguments (unable to resolve constructor)
Would this code be in C# I would use typeof() but in JAVA there is nothing like this maybe instanceof but I cannot use this at this point. Btw .values() is returning an Array of the same type class (enum).
How can I solve this problem?
//edit
with the method .getReturnType() on the Method I would get the return type but I cannot apply it to the DataHandlerSetAdapter<>
Class DataHandlerSetAdapter
public class DataHandlerSetAdapter<T> implements DataHandler<T> {
private final Set<T> values = new ConcurrentSkipListSet<>();
.
.
.
}
It is not clear to me what you are trying to do. But if the loadable class is an enum, then why you are not doing it like this:
Class<? extends Enum<?>> clazz = classLoader.loadClass(d);
Enum<?>[] values = clazz.getEnumConstants();
RSA.addDataHandler(clazz, new DataHandlerSetAdapter<>(values));
Alternatively you can use raw types:
RSA.addDataHandler(clazz, new DataHandlerSetAdapter(values)) - note no diamonds <>.
But Still I'm not sure weather will this work for you or not. Please provide the following information to understand the root cause of failure.
Signature of DataHandlerSetAdapter constructor
Signature of RSA.addDataHandler(...) method
More info about RSA you used in your code snippet. (e.g. Is it a class or object)
I have a utility class for interacting with the Datastore (GAE's in-built Datastore in my case) and it has methods like:
//Class GaeDataUtil
public static <T> Optional<Key<T>> saveEntity(T entity)
(Optional is from the Guava library and Key<T> from Objectify, although I doubt any of this makes a difference.)
I want my (minimal) hierarchy of entities to have a .save() method. So that for:
public class User extends RootEntity
where RootEntity provides:
public Optional<Key<T>> save() {
//Skipping the error-handling.
return GaeDataUtil.saveEntity(this);
}
I can write:
User myUser = new User();
// set some properties
Optional<Key<User>> optKey = myUser.save();
But of course that doesn't work because a call to myUser.save() returns Optional<Key<RootEntity>> not Optional<Key<User>> as I want.
I can avoid this issue by typecasting in User.save() (and Account.save() and Project.save() etc. etc.) and suppressing warnings, but even if there are only (say) 10 entity classes extending RootEntity, that's still a fair bit of boilerplate code to write just to typecast. Also, I think that much of the benefit of having a class hierarchy is lost if I have to write code (however minimal) for every derived class (there will be other, similar methods too).
Is there a better solution to this?
Update: using Java 7.
You will just need to type cast it to the Generic type T in the RootEntity.save() method.
public <T> Optional<Key<T>> save() {
//Skipping the error-handling.
return (Optional<Key<T>> GaeDataUtil.saveEntity(this); // This line will generate a warning.
}
And then when you write,
Optional<Key<User>> optKey = myUser.save();
It will automatically be inferred correctly because of Target Type Inference.
One solution is to parameterize RootEntity something like this:
class RootEntity<Subclass extends RootEntity> {
public Optional<Key<Subclass>> save() {...}
}
Then define your subclass like:
class User extends RootEntity<User> {...}
I've used this pattern before. If there is a slicker solution, I'll be eager to see it. :)
This is what finally worked:
public <T extends RootEntity> Optional<Key<T>> save1() {
#SuppressWarnings("unchecked")
Key<T> key = (Key<T>) ofy().save().entity(this).now();
return Optional.fromNullable(key);
}
Doing this in two steps works (get the Key, then wrap it up in an Optional) --- it let's the Target Type Inference work correctly. Doing it in a single step doesn't:
public <T extends RootEntity> Optional<Key<T>> save2() {
return (Optional<Key<T>>) Optional.fromNullable(ofy().save().entity(this).now());
}
This second form as suggested by #Codebender shows an error (Cannot cast from Optional<Key<RootEntity>> to Optional<Key<T>>), not a warning in Eclipse.
However, the basic idea by #Codebender of using Target Type Inference was sound.
I have the following setup of classes/interfaces.
Interface IFoobar
Class BaseClass which implements IFoobar and is abstract
Class ConcreteClassA which extends BaseClass
Class ConcreteClassB which extends BaseClass
Class ConcreteClassC which extends BaseClass
I have a method for which I need to pass instances of java.lang.Class for the above concrete classes. I am declaring it like so.
void doSomething(String id, Class<IFoobar> c)
However, when I try to compile, java complains with an error more or less like this:
doSomething(java.lang.String,java.lang.Class<IFoobar>) in javaclass cannot be applied to
(java.lang.String,java.lang.Class<ConcreteClassA>)
register("12345", ConcreteClassA.class);
^
1 error
I've only recently needed to use java.lang.Class to do things, so I am guessing I am missing something simple. I would have expected the typed class declaration to work like normal parameters in that the concrete classes are recognized as instances of the interface, but this apparently isn't the case.
I've tried various methods of casting, etc and either not had the desired results, or had code which isn't valid. So any ideas as to what I need to do would be appreciated.
Thanks in advance.
A variable of type Class<IFoobar> can only hold a reference to a Class<IFoobar> object, not a Class<ConcreteClassA> object.
Change Class<IFoobar> to Class<? extends IFoobar>.
This behaviour is not particularly sensible for Class objects. It is much more logical for collections, where it stops you doing this:
void method1(List<IFoobar> list)
{
list.add(new ConcreteClassA());
}
void method2()
{
List<ConcreteClassB> list = /* something */;
method1(list);
// oops! we put a ConcreteClassA inside a List<ConcreteClassB>
}
the only accepted value for Class<IFoobar> is IFooBar.class. If you want to accept IFooBar.class and all its subclasses, you should use Class<? extends IFooBar>
The error has nothing to do with "Class"
Simply if you use
ArrayList<Object> x = new ArrayList<String>();
You get error: incompatible types
because, though the String class is a subclass of Object, ArrayList<Object> is a different type than ArrayList<String>. That is the nature of Generics.
You can use
void doSomething(String id, Class c)
I'm using mockito 1.9.5.
I have the following code:
public class ClassA {
public List<? extends MyInterface> getMyInterfaces() {
return null;
}
public static void testMock() {
List<MyInterface> interfaces = new ArrayList<>();
ClassA classAMock = mock(ClassA.class);
when(classAMock.getMyInterfaces()).thenReturn(interfaces);
}
I get a compilation error for the thenReturn(interfaces) saying:
"The method thenReturn(List<capture#1-of ? extends MyInterface>) in the type
OngoingStubbing<List<capture#1-of ? extends MyInterface>> is not applicable for the arguments
(List<MyInterface>)"
However, when I use the thenAnswer method of mockito, I don't get the error. Can anyone tell me what's going on? Why do I get the error when I use the thenReturn method?
Is there any other way to solve this problem when ClassA is provided by a 3rd party and cannot be modified?
EDIT : Starting from Mockito 1.10.x, generics types that are embedded in the class are now used by Mockito for deep stubs. ie.
public interface A<T extends Observer & Comparable<? super T>> {
List<? extends B> bList();
T observer();
}
B b = deep_stubbed.bList().iterator().next(); // returns a mock of B ; mockito remebers that A returns a List of B
Observer o = deep_stubbed.observer(); // mockito can find that T super type is Observer
Comparable<? super T> c = deep_stubbed.observer(); // or that T implements Comparable
Mockito tries its best to get type information that the compiler embeds, but when erasure applies, mockito cannot do anything but return a mock of Object.
Original : Well that's more of an issue with generics than with Mockito. For generics, you should read what Angelika Langer wrote on them. And for the current topic, i.e. wildcards, read this section.
But for short, what you could use is the other syntax of Mockito to help with your current situation :
doReturn(interfaces).when(classAMock).getMyInterfaces();
Or with the BDD aliases :
willReturn(interfaces).given(classAMock).getMyInterfaces();
Nevertheless, you could write wrappers that are more generic friendly. That will help future developers working with same 3rd party API.
As a side note: you shouldn't mocks type you don't own, it can lead to many errors and issues. Instead you should have some wrapper. DAO and repositories for example represent such idea, one will mock the DAO or repository interface, but not the JDBC / JPA / hibernate stuff. There are many blog posts about that:
http://davesquared.net/2011/04/dont-mock-types-you-dont-own.html
http://blog.8thlight.com/eric-smith/2011/10/27/thats-not-yours.html
https://web.archive.org/web/20140923101818/http://freshbrewedcode.com/derekgreer/2012/04/01/tdd-best-practices-dont-mock-others/
...
Another solution (albeit less readable) is to qualify the static method call of when to bind the wildcard:
Mockito.<List<? extends MyInterface>>when(classAMock.getMyInterfaces()).thenReturn(interfaces);