If I have
public abstract class SomeType<T extends SomeOtherType> {}
public class WrapperType<U extends SomeType<T>> {}
Is there a way to modify the latter signature (which is an error 'cannot resolve symbol "T"') so that I can use the generic type in WrapperType, say for List<T> or something analogous?
(If I have posed this question using the wrong terminology, I'd appreciate the corrections.)
It's quite simple once you realize what's going on. You didn't define T in the scope of the class WrapperType. Declare it with at least the same bounds as in SomeType.
class WrapperType<T extends SomeOtherType, U extends SomeType<T>> {}
Related
I apologize in advance, I'm sure this has been asked before, but I'm a self-learned programmer so I can't for the life of me figure out the terms I need to search for.
I have a generic class:
public abstract class Directory<T extends Key>
It is a generic parameter of another class:
public class TagDescriptor<T extends Directory, U extends Key>
The U of TagDescriptor will always be the generic parameter of the Directory passed as the first parameter. It's fine to pass the T, but is there no way to infer the U? I've tried things like:
public class TagDescriptor<T extends Directory<U>>
But that's incorrect. At compile time it should know that Directory has a generic; can I leverage that?
You can declare multiple types parameters bounded with self-reference:
public class TagDescriptor<K extends Key, T extends Directory<K>>
NB: K is commonly used, as a name, for key types.
As for, why is it necessary to declare the type parameter K? Well it's quite simple : because otherwise the compiler has no way to tell what K is : a concrete class, an interface named K ? Or a type parameter named K ?
For instance, this would be perfectly legal:
public interface K {}
public class TagDescriptor<T extends Directory<K>>
In java, can I do something -more or less- like this? and how?
public class SomeGenericClass<T> extends T{
}
I think this is the relevant quote from the JLS (§8.1.4):
The ClassType [provided in the extends clause] must name an accessible (§6.6) class type, or a compile-time error occurs.
(The bit about accessibility isn't relevant).
A class type is not the same thing as a type variable (§4.3) (which T is), so attempting to do this would be a compile-time error.
you can't do public class SomeGenericClass<T> extends T for multiple reasons:
Type erasure will erase T to Object., and it would be pointless to say public class SomeGenericClass<T> extends Object ,as Object is already the base class of all types.
Imagine if it were allowed and i did something like public class SomeGenericClass<T extends Comparable> extends T , type erasure will turn this into public class SomeGenericClass<Comparable> extends Comparable but interface is implemented not extended .
public class SomeGenericClass<T> extends T{
}
You must understand Generics better. SomeGenericClass is a template (C++ terminology). As it is, it means nothing to compiler. You cannot write
SomeGenericClass<T> obj = new SomeGenericClass<T>() // this is invalid
Instead you need to supply the type attribute. This information complements the above answer provided by #Andy Turner
I've use this method to retrieve the type of my generic, and no problem... until now
Now, I've got this kind of structure:
public class Toto<T> extends OtherOne<X,Y,Z> {...}`
and when I use the
((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];`
it's return me the type Class<X> of my OtherOne class, not Class<T>!
Has anyone ever encountered this problem? Whatever I've tried didn't work, and I don't want to use this solution of getting the class as an argument of my Constructor.
In order to learn what T is it will have to be captured in a subclass. Ex:
public class StringToto extends Toto<String> {}
Class<?> t = (Class<?>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
This is the case since types are only retrievable at runtime if they're part of a type definition.
I have
1) a basic interface,
2) a few classes that implement this interface,
3) and a generic class that I want to accept, as a parameter, any of the implementing classes
I have tried the following:
public class Foo extends Bar<? extends SomeInterface> {
public Foo(List<? extends SomeInterface> someInterfaceList) {
super(someInterfaceList);
}
...
}
I receive the error No Wildcard Expected. Elsewhere in my code I have statements such as List<? extends SomeInterface> and I receive no errors, so why am I running into problems here? How can I fix this problem and still get the desired results?
I have tried search 'No Wildcard Expected' and 'wildcard in class declaration' to no avail. Thanks in advance!
It sounds like you want to declare a generic type argument that you will reference elsewhere. Wildcards only make sense when the type is used only once, and when declaring a generic type parameter for a class this doesn't make any sense.
Try this instead:
public class Foo<T extends SomeInterface> extends Bar<T> {
public Foo(List<T> someInterfaceList) {
super(someInterfaceList);
}
...
}
As your code was written, there was no way for the user of your class to specify the generic type argument for Bar<>, since Foo wasn't itself a generic type.
Further, if this were possible, it would have been possible for the generic argument to Bar<> to be different than the generic argument to List<> -- as long as both types implemented SomeInterface there would not be a compile-time issue with these definitions, but there could have been a much more confusing error message later when you incorrectly assumed that both types must be the same.
So, declare the generic type once as a generic argument to the Foo class, and then use that type (T in my example) elsewhere to refer to that type instead of accepting some new generic type argument that may not refer to the same type.
I'm not exactly sure what you're looking for, so it might help if you could provide a little more detail. Perhaps you could be a little more specific about how you're planning to instantiate and use these objects?
Anyways, I think you might be looking for something like this:
import java.util.List;
public class Foo<T extends SomeInterface> {
public Foo(List<T> someInterfaceList) {
for (T item : someInterfaceList) {
// do something with each item
}
}
}
class Bar<T> {}
interface SomeInterface<T> {
T x(T y);
}
Or, alternatively, you could just use the following for the constructor:
public Foo(List someInterfaceList) {
but you wouldn't have an easy way of getting the type T of the items in the list.
I have a class defined like so:
public class AddRecordsToolbar<D extends IDataSource<T>, T extends Serializable>
extends AbstractToolbar<D, T>
which my IDE IntelliJ IDEA declares as legal. It looks and feels wrong to me.
I want to declare it like this:
public class AddRecordsToolbar<D extends IDataSource<T extends Serializable>, T>
extends AbstractToolbar<D, T>
however that syntax is illegal thanks to something to do with Javas type erasure.
D extends IDataSource<T> is required by the superclass.
My Class is using Serializable to do a deep copy. Hence the T extends Serializable.
So now on to the Question: If I specify T extends Serializable as the second type parameter for my class will it still enforce T extends Serializable for D as well?
Answering to your question, yes its do.
The order of generic parameter it only in your mind.
If we would rephrase that implementation to:
public class AddRecordsToolbar<T extends Serializable, D extends IDataSource<T>> extends AbstractToolbar<D, T>
you will be not so surprised, and looks that the way it should be.
I will try to find the explanation for this in Java Language Specification (when it will work) but for now that the way it is.
I believe that this is addressed in section 8.1.2 of the java language spec:
The scope of a class' type parameter is the entire declaration of the
class including the type parameter section itself. Therefore, type
parameters can appear as parts of their own bounds, or as bounds of
other type parameters declared in the same section.
Yes. The "T" in the second parameter is the same T as in the first. Nothing world work, otherwise.
This means that
class IFoo extends IDataSource<String>{};
AddRecordsToolbar<IFoo, Integer> x;
Is illegal. Integer and String are both serialisable, but the declaration of AddRecordsToolbar says that the data source has to be a source of the data type in your second parameter. And that second parameter says that it has to be serializable.