Why cannot generic extend a non-generic class in Java? - java

It looks like a generic class in java cannot extend a regular non-generic class. What is the reason for that? Is there any workaround?
I was mistaken. As ColinD pointed out my problem was actually with exceptions. Can anybody explain why generic exceptions are not allowed in Java?

public class A {
}
public class B<T> extends A {
}
Works without any problems.

Java seems to do it :
public abstract class AbstractCollection<E>
extends Object
implements Collection<E>
Do you have some code, so we can see the problem?

Because exceptions catching require the jvm to know the exact type of exception at runtime (reification) which is not possible in java because all type parameter information is erased by the compiler

You can! - with certain restrictions. Exceptions are one of those restrictions. You can't make them generic. Erasure removes the exception type information preventing the exception hierarchy from working if you threw generic versions of exceptions. Too bad :(.
Consider this:
import org.apache.commons.collections.set.UnmodifiableSet;
import org.apache.commons.beanutils.BeanMap;
//Can't do this:
//public class MyBeanMap<K, V> extends BeanMap implements Map<K,V>{
//Can do this:
public class MyBeanMap<K, V> extends BeanMap {
//Can't make actual method calls return generic types.
public V get(V arg0) {//Name clash
...
return (V)retval;
}
//Also can't do this:
#override
public V get(V arg0) {//Name clash
return (V)retval;
}
}
I guess you could throw UnsupportedOperation exceptions in overridden methods for the existing interface, and implement your own new generic methods:
public V getGeneric(V){
...
}
but that seems a lot uglier than implementing a facade pattern and just extending the map code, but that is a LOT of intermediate code to create a facade for.

Related

Kotlin Conflicting overloads: public open fun statements()

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
}
}

Java GenericClass< ? extends Interface> as a Parameter

public interface A {}
public interface B {}
public class Test implements A{}
public class Test2 {}
I made a method which checks if a class implements an interface. I want my method to only accept generic interfaces and not all class objects.
method
public static boolean containsInterface(Class clazz, Class intf)
{
try
{
Validate.isTrue(intf.isInterface());
if(clazz.isInterface())
return JavaUtil.isClassExtending(intf, clazz);
for(Class c : ClassUtils.getAllInterfaces(clazz))
{
if(JavaUtil.isClassExtending(intf, c))
return true;
}
}
catch(Throwable t)
{
t.printStackTrace();
}
return false;
}
Since Test.class & Test2.class are not interfaces on the 2d parameter I want it to have a compile error since the 2d parameter must be an interface class
containsInterface(Test.class, Test.class);
containsInterface(Test.class, Test2.class);
acceptable use of my method
containsInterface(Test2.class, A.class);
containsInterface(Test.class, B.class);
what I tried
public static boolean containsInterface(Class clazz, Class<? extends Interface> intf)
I currently check if the class in the parameter is an interface then throw an exception. I would rather force people to not be able to call the method to begin with if it's not an interface
I am aware of Annotations and Enum objects are available to use as a class signature to make sure people are using the parameters right but, I can't seem to find the one for the interface itself.
I was told generics do not support interfaces or abstract classes type is this true even in jre 9-13+
You cannot force argument to be ANY interface implementation using type control system. The same would apply if you would like to eg force only Class<?> with abstract modifier. I am not sure if that is really needed as doing simple type isInterface assert is
Straigthforward
Clean
Robust
Easy to understand
Error prone
Testable
JDK Engineers does not care about that either. As an perfect example of such mechanism would be used (but there is none) is JDK Dynamic Proxy creation. You can create only create proxy of an interface (or set of) but not of class.
I don't think that it is just worth of the effort to write own preporocessors. Moreover it would be not universal - as you assume that runtime type must be know at compile time - what about dynamically loaded classes etc?
Intefaces in java has no super class that you can use in generic mode.
If you try get the super class of an interface with reflection returns null.
public static void main (String [] args) {
System.out.println(A.class.getSuperclass());
}
interface A {}
Output:
null

Name Clash, override fail, on a class implementing two interfaces with same erasure

I am creating a class that overrides a method signature whose erasure is identical between 2 implemented interfaces, but with a minor difference in regards of the generic type (one is a method-inferred type, the other an inferred-class type). I am looking for a neat solution. I CAN ONLY edit the inherited class, not the original legacy interfaces.
To show the case, I made up an abstract sample, to understand the problem:
I got a Developer legacy parent class:
public class Developer<C>{
Rate<C> getRate(Taxes<C> tax){ /*...*/ }
}
I also got a Rentable legacy interface, with an almost identical signature
public interface Rentable {
<C> Rate<C> getRate(Taxes<C> taxes);
}
As a developer is not rentable, in my model, I create an special
developer which is both a Developer, and Rentable material.
public class OutsourcableDeveloper<C>
extends Developer<C>
implements Rentable{
#Override
public Rate<C> getRate(Taxes<C> taxes){ /*...*/}
}
and then I got the infamous
Name clash: The method getRate(Developer.Taxes) of type
OutsourcableDeveloper has the same erasure as
getRate(Developer.Taxes) of type Rentable but does not override it
How can I get rid of it, so OutsourcableDeveloper.getRate() hides
both Developer and Rentable. getRate()?
It seems a bit illogical to fail a common override but then disallowing extending both signatures as the erasures are equal.
Does it really matters so much the fact that one of the supertypes infers type from de method and the other from the class specially when I'm not going to call any super in my implementation? Is there perhaps a trick to overcome the issue given this simplification?
EDIT: I opened a more abstract, less solution-oriented to my actual problem, question to discuss the inheritance design problem which I believe is the correlated essence of the actual issue I am having: Why can't I extend an interface "generic method" and narrow its type to my inherited interface "class generic"?
EDIT2: Previous question lead me to the answer posted here
Well they are actually not equal. Because any Rentable-Instance allows any typeparameter T to be given, while the OutsourcableDeveloper restricts it.
Of course you can assume that in your case it is easy to use the
<C> Rate<C> getRate(Taxes<C> taxes);
Version of the interface. But expect how confused a developer could be, if he wants to subclass OutsourceableDeveloper. From the definition of Developer he can assume that the Method getRate is fixed to C but actually it can suddenly take any value. -> allowing this would lead to confusion.
What i can offer you is the following code-example, which may be suitable for your case. Although it definitely will be inconvenient to use it. But as you forward all methods to the OursourcableDeveloperRentable it is possible. The comments should explain how it works.
//This class itself can be added to any Developer-lists
public class OutsourcableDeveloper<C> extends Developer<C> {
public final OutSourcableDeveloperRentable RENTABLE_INSTANCE = new OutSourcableDeveloperRentable();
#Override
public Rate<C> getRate(final Taxes<C> taxes) {
// Simply forward to the more general getRate instance.
return this.RENTABLE_INSTANCE.getRate(taxes);
}
public void exampleBehaviourA() {
//Example for how you can make both objects behave equally.
}
// This class can be added to the lists requiring a Rentable
// And the original value can be retrieved by both classes.
public class OutSourcableDeveloperRentable implements Rentable {
public final OutsourcableDeveloper<C> PARENT_INSTANCE = OutsourcableDeveloper.this;
//This method is the one to implement because it is more general than
//the version of OutsourcableDeveloper.
#Override
public <T> Rate<T> getRate(final Taxes<T> taxes) {
// Do your work.
return null;
}
public void exampleBehaviourA() {
//Just an example - Maybe for you it makes for sence to
//forward the method of Oursoursable-Developer to here.
//Then all Behaviour would be found in this class.
OutsourcableDeveloper.this.exampleBehaviourA();
}
}
}
Ok, I found a way to solve it. It's clumpsy, but it's the easier one if the architecture is not very complex, inspired by my Why can't I extend an interface "generic method" and narrow its type to my inherited interface "class generic"? own answer:
public class OutsourcableDeveloper<C>
extends Developer<C>
implements Rentable{
/* This might not be needed if we don't need to extract C from taxes parameter */
final Class<C> currencyClass;
public OutsourcableDeveloper(Class<C> currencyClass){ this.currencyClass = currencyClass;}
#Override
public Rate<C> getRate(#SuppressWarnings("rawtypes") Taxes taxes){
try{
C taxesCurrency = (C) currencyClass.cast(taxes.getCurrency()); //IF actually needed getting the typed instance
return new Rate<C>(taxesCurrency); //Or whatever processing
} catch (ClassCastException e){
throw new UnsupportedOperationException("OutsourcableDeveloper does not accept taxes in a currency that its not hims");
}
}
}
It is also possible to play with "extends Developer" without the generic type, so it is implictly raw. but we loose typing for the non-conflicting methods as well

When called on a derived class, have a generic method defined in base class return derived class type in Java

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.

How do I configure Google-Guice using a generic interface?

I have a bunch of entity type factories that derive from a common, generic interface. For instance,
public class ConnectionFactory implements IEntityFactory<Connection> { ... }
I'd like to use Google-Guice to break hard dependencies on these factories.
However, there's a syntax error when I try to configure Guice:
public class EntityFactoryModule extends AbstractModule {
#Override
protected void configure() {
bind(IEntityFactory<Connection>.class).to(ConnectionFactory.class);
}
}
Eclipse says "IEntityFactory cannot be resolved to a variable."
Can someone please help me understand why this doesn't work? Also, is there an alternate syntax that will work?
My Guice-fu is generally limited, but I think you want a type literal here:
bind(new TypeLiteral<IEntityFactory<Connection>>() {})
.to(ConnectionFactory.class);
One method is to declare a new interface:
interface IConnectionFactory extends IEntityFactory<Connection> { ...}
Then I can do:
bind(IConnectionFactory.class).to(ConnectionFactory.class);
But, there's already an interface explosion going on in my project.
Is there a better way?

Categories

Resources