Bounded type parameters - get type - java

I have such class:
public abstract class Test<T extends List<?>> {
public abstract void handle(? arg);// ? - obviously won't work
}
Is there any way to "know" the type of list element in the Test's subclass?

You could use a named generic type parameter instead of ?.
Something like this:
public abstract class Test<E, T extends List<E>> {
public abstract void handle(E arg);
}

Related

How to solve an `unchecked` Java warning about a Class requiring to extend from a specific class?

In my Android Java application I have a method:
private <T extends Message> ReturnObject doSomething(Class<T> type) {
// Implementation
}
As you see parameter type should extend of class Message.
Now, this is the case; I call the method doSomething like:
#Override
public void myMethod(Class type){
doSomething(type);
}
Notice that my method overrides another method.
The warning that pops up:
[unchecked] unchecked method invocation: method doSomething in class
Class is applied to given types
required: Class<T>
found: Class
where T is a type-variable:
T extends Message declared in method <T>doSomething(String,Class<T>)
How can I solve this warning?
#Override
public void myMethod(Class type) {
Class<? extends Message> mtype = type.asSubclass(Message.class);
doSomething(mtype);
}
Best would be to remove the non-generic type-unsafe overriden method:
public void myMethod(Class<?> type) {
And even more best to repair the base class method.
You might want to pass the Class type in the parameter and not just the Class like this below
#Override
public void myMethod(Class<T> type){//I've changed the parameter from Class to Class<T>
doSomething(type);
}
It should look like
public <T extends Message> void myMethod(Class<T> type){
doSomething(type);
}

How to satisfy parameter type Class<? extends someInterface> in java

Consider the following code
#Test
public void testFunction() {
// This cause error
callDoSomething(new myInterfaceImpl());
}
public interface myInterface {
int doSomething();
}
public class myInterfaceImpl implements myInterface {
public int doSomething() {
return 1;
}
}
public void callDoSomething(Class<? extends myInterface> myVar) {
System.out.println(myVar.doSomething());
}
On this line callDoSomething(new myInterfaceImpl()); I get the following error.
Error:(32, 25) java: incompatible types: com.myProject.myTest.myInterfaceImpl
cannot be converted to java.lang.Class<? extends com.myProject.myTest.myInterface>
How do I satisfy the parameter type? If only an interface is provided to me.
I want to bound the class that has an interface, but it seems like this is not avaiable to me
Class<? implements myInterace>
Edit:
The reason I want to do this is because I want to provide a custom kafka partitioner.
public Builder<K, V> withCustomPartitionner(Class<? extends Partitioner> customPartitioner) {
this.customPartitioner = customPartitioner;
return this;
}
It looks like you want to be able to call methods on the parameter that's given. In that case, you'll want the actual instance of your interface, not the Class associated with it.
public void callDoSomething(myInterface myVar) {
System.out.println(myVar.doSomething());
}
Class<> is used when you want to use reflection to do something with the specific class type that you're interested in:
public void outputClassInfo(Class<? extends myInterface> myClass) {
System.out.println(myClass.getName());
}
If that's what you're going for, you'll want to provide the class at compile time like this:
outputClassInfo(myInterfaceImpl.class);
Or, if you won't know which class you're dealing with until runtime, you can use reflection:
myInterface thing = getThing();
outputClassInfo(thing.getClass());
So, in the example you're providing in your edit, I'm guessing you want:
public Builder<K, V> withCustomPartitioner(Class<? extends Partitioner> customPartitioner) {
this.customPartitioner = customPartitioner;
return this;
}
// Usage
builder
.withCustomPartitioner(FooPartitioner.class)
...
This type Class<? extends myInterface> myVar corresponds to a Class instance not to an instance of myInterface.
You generally don't pass a class as parameter (but for reflection purposes or to bypass generics erasures). So what you need as parameter is probably :
public void callDoSomething(myInterface myVar) {
System.out.println(myVar.doSomething());
}
That you could invoke :
#Test
public void testFunction() {
// This cause error
callDoSomething(new myInterfaceImpl());
}
The parameter to callDoSomething shouldn't be a class. It must be an instance of that class or it's subclass.
public <T extends myInterface> void callDoSomething(T myVar) {
System.out.println(myVar.doSomething());
}
On a side note, don't name Java classes/interfaces starting with lower case.
As rightly mentioned by Andy Turner#, there is no need to use a type parameter here and you can just refer to the type as myInterface
public void callDoSomething(myInterface myVar) {
System.out.println(myVar.doSomething());
}
You need to pass the Class not an instance.
callDoSomething(MyInterfaceImpl.class);

Overriding Method with Generic Parameters from Abstract Class

I am unable to compile a method which needs to override a method from an abstract class supertype which uses generics for one of the parameters. The compiler complains that the extending class' setRef() method does not override a method from the supertype.
Parent Abstract Class:
public abstract class AbsClass<Q extends Interf> {
public abstract Ref<? extends AbsClass<Q>> getRef();
public abstract <M extends AbsClass<Q>> void setRef(Ref<M> newRef);
}
Ref is:
public interface Ref<M extends AbsClass<? extends Interf>> { }
and Interf is:
public interface Interf { }
Extending Child Class (setRef() doesn't compile):
public class ChildClass extends AbsClass<InterfImpl> {
#Override
public Ref<ChildClass> getRef() {
return null;
}
#Override
public <M extends ChildClass> void setRef(Ref<M> newRef) {
return null;
}
}
I have also tried using wildcards, and received same error. With wildcards, the abstract class' setRef() is:
public abstract void setRef(Ref<? extends AbsClass<Q>> newRef);
and the extending class' setRef() is:
public void setRef(Ref<ChildClass> newRef)
or even:
public void setRef(Ref<? extends ChildClass> newRef)
The only way I can get it to compile is if the extending class' setRef() uses the abstract class' type:
public <M extends AbsClass<Interf>> void setRef(Ref<M> newRef)
But I would like to limit the typing of the newRef parameter to be Ref<ChildClass> or subtypes, so this isn't perfect. How can I get my extending class to only allow ChildClass or its subtypes for the setRef() method's newRef parameter? Part of my confusion is that the ChildClass' getRef() return value handles the generic typing just fine, and the same "signature" on setRef()'s parameters fails to compile. Help? Thanks!
The problem with setRef is that you could access an instance of ChildClass through a variable of type AbsClass<? extends Interf> and thus the parameter type for setRef would look like <M extends AbsClass<? extends Interf>> which again could be any M but which also doesn't match <M extends AbsClass<Q>> since Q has been defined to be InterfImpl in your case.
You could change ChildClass to this:
public <M extends AbsClass<InterfImpl>> void setRef(Ref<M> newRef)
but this would still allow any M and you can't just use Ref<ChildClass> because what I said above, i.e. the compiler wouldn't know about Ref<ChildClass> if you used a variable of type AbsClass<InterfImpl> or even AbsClass<? extends InterfImpl>.
One way to allow only for ChildClass parameters would be to use ChildClass in the generic type as well, e.g. like this:
public abstract class AbsClass<Q extends Interf, M extends AbsClass<Q, M>> {
public abstract Ref<M> getRef();
public abstract void setRef(Ref<M> newRef);
}
public class ChildClass extends AbsClass<InterfImpl, ChildClass> {
public Ref<ChildClass> getRef() { return null; }
public void setRef(Ref<ChildClass> newRef) { }
}
You are getting an error because in AbsClass.setRef(), your parameter is of type Ref<? extends AbsClass<Q>>
But in your ChildClass.setRef() the parameter is of type Ref<? extends ChildClass>.
For overriding, a subclass should have the same typed parameters in the method as it's parent (before type erasure when using Generics).

How to properly override an abstract method with generics in the signature

I thought I understood how to do this but I'm getting some unexpected behavior so apparently I'm missing something. Here's the problem boiled down.
Base Class:
public abstract class Base<T>
{
abstract public void foo(List<? extends T> l);
}
Derived Class:
public class Derived<T> extends Base
{
#Override
public void foo(List<? extends T> l) { return; }
}
The Base class complies fine, but when I compile the Derived class I get:
Derived.java:3: Derived is not abstract and does not override abstract method foo(java.util.List) in Base
public class Derived extends Base
^
Derived.java:5: method does not override or implement a method from a supertype
#Override
^
2 errors
The generics of the parameter List<? extends T> appears to be the cause of the problem. If I replace that part in both signatures with the basic type int it comples fine.
Can anybody tell me what's going on here?
You should do
public class Derived<T> extends Base<T>
You need to specify <T> for Base otherwise you will have to override method by simply declaring List i.e.without generics
You can also pass the type parameter in your class declaration like this:
public class Derived extends Base<SomeConcreteType> {
#Override
public void foo(List<SomeConcreteType> l) {
// ...
}
}
if you no longer need the generic part of the abstract class because you are going to use a concrete type in your derived class. Otherwise you have to do what the other answer stated.

Is there any better solution for abstract class A<T extends A>?

I want to override a method and replace a parameter it takes with a subclass of that parameter.
For return type there is no problem, because they are not a part of method signature and can be replaced with subclasses (called "covariant return type"). For arguments this is not working, because they are a part of signature.
So I came out with solution to use generic parameter of the same type:
public abstract class A<T extends A> {
public void loadValuesFrom(T source) {
...
}
}
public class B extends A<B> {
public void loadValuesFrom(B source) {
super.loadValuesFrom(source);
...
}
}
But the statement "public abstract class A" looks odd to me. Are there any other ways to achieve this? Any "covariant parameter type"? :-)
If it must be a parameter type, using generics is probably the best option. I'd only do a minor correction to avoid the raw type in the class declaration:
public abstract class A<T extends A<T>> {
If however you have the special case where the object being initialized needs to be freshly created, you might include creation in a method, thereby removing the need to pass that object as parameter:
public abstract class A {
public A clone() {
}
}
public class B extends A {
public B clone() {
// copy state
}
}

Categories

Resources