What does "T extends Junk" mean in a generic class in Java? - java

I'm trying to understand this notation of whats going on here Example also below. I'm looking to see if anyone can supply additional code to help me make sense of this. How do I extend junk with T? what does that imply?
public class Junk<T extends Junk>
{
public Junk()
{
}
public T returnType()
{
return null; //? what would I even return
}
//what would I do to make sense of this class
}

T is a generic type parameter. You know it is a Junk, or a subclass of it. To return anything useful from your method, you'd need some other methods using the same type. For example:
public class Junk<T extends Junk> {
T var;
public void setT(T var) {
this.var = var;
}
public T returnType(){
return var;
}
}
It can be used by creating instances where the type parameter is specified:
Junk junk = new Junk<Junk>();
junk.setT(new Junk<Junk>());
junk.returnType();
This is more useful than simply using "Junk" instead of "T", because subtypes can be used without losing type-safety. If you have a subclass SubclassJunk, then you can do:
Junk junk = new Junk<SubclassJunk>();
junk.setT(new SubclassJunk<Junk>());
SubclassJunk subclass = junk.returnType();

pardon me for making an educated guess, but,
It looks like T is an undefined type,
the statement <T extends junk> looks like a constraint to ensure that T derives from Junk
so if you have a class like
public class SmallJunk extends Junk
{
}
then T can be aSmallJunk, but not other types.

class Junk<T extends Junk> is the syntax for generic programming in Java. It means that wherever the type T is used in the class, it must stand for some (as yet unknown) subclass of Junk.

Given
public class junk<T extends junk<T>>
{
public T returnType()
{
return (T)this;
}
}
you would extend it as
public class Subclass extends junk<Subclass> {
}
and the inherited returnType method would then return Subclass. The most prominent example of this pattern in the standard Java libraries is enum types, where an enum Foo becomes a class that extends Enum<Foo>

Related

Java not allowed to call recursive method with generic type?

public class ResourceAssembler<T extends BasedEntity> {
public Resource<T> toResource(T entity) {
ExtendsBasedEntity e = getExtendsBasedEntity();
toResource(e); //<----compile error
//some other code
}
}
public class ExtendsBasedEntity extends BasedEntity{}
But if you call it from the outside its fine
//some other class
new ResourceAssembler<ExtendsBasedEntity>().toResource(new ExtendsBasedEntity())
Why?
Error:(28, 25) java: incompatible types: spring.BasedEntity cannot be converted to T
T may not be ExtendsBasedEntity, but some other subtype of BaseEntity, hence the compile error.
One way to "fix" the problem, is to use a type token
public class ResourceAssembler<T extends BasedEntity> {
private final Class<T> type;
public ResourceAssembler(Class<T> type) {
this.type = type;
}
public Resource<T> toResource(T entity) {
toResource(type.newInstance());
//some other code
}
}
Assuming that works for you.
Let's create two classes extending BasedEntity and call them EBE1 and EBE2.
Now you create a ResourceAssembly object using EBE1 as the type parameter. But let's say that in the implementation of the toResource method you do something like return toResource(new EBE2());.
So the return type of toResource() is becoming Resource<EBE2> but that is wrong because according to the structure you should return Resource<EBE1>. And that's why the compile time error. And type safety instincts of Java kicks in.
If you want to do return a generic for the toResource method then you either have to pass in the entity object down as it is or change it to the concrete type that you are initializing it within and not use generic (although I don't know why would anyone use the second option, but it's a "solution" to make it "compile").
Also, on the outside when you declare it. You are not specifying the type parameter for ResourceAssembly and hence it's a raw one. Try to do it with a type param. You will have red squiggly lines there as well.
Here is an example:
static class Resource<T> {
}
static class BasedEntity {
}
static class ExtendsBasedEntity1 extends BasedEntity {
}
static class ExtendsBasedEntity2 extends BasedEntity {
}
static public class ResourceAssembler<T extends BasedEntity> {
public Resource<T> toResource(T entity) {
return toResource(new ExtendsBasedEntity1()); //<----compile error
}
}
public static void main(String[] args) {
new ResourceAssembler<ExtendsBasedEntity1>().toResource(new ExtendsBasedEntity1()); // <---- No errors or warnings. This is valid and legal
new ResourceAssembler<ExtendsBasedEntity2>().toResource(new ExtendsBasedEntity1()); // <----- red squiggly lines here
new ResourceAssembler().toResource(new ExtendsBasedEntity2()); // <--compiler warning about raw types but no error
}
If you anyhow need to make it work the way you want it to, then instead of returning Resource<T>, return Resource<ExtendsBasedEntity> because you are recursing inside a generic method and looks like you need an object of concrete type to go in as the parameter for the recursive call. So it would make sense to do so.
Or else, go with #Bohemian's approach and make sure that in the class declaration of the type that you are using, there is a no-args constructor or else you will be having InstantiationException.

How to return `this` in the generic class?

For example, I have a some class:
public class Test<T> {
public T setField() {
return this;
}
}
Of course, it's an incorrect class. But can I write it some else? (to it hasn't errors).
P.S. I know that I can write an abstract method to override it in the child class. But I ask about the generic class only (in the its class body only).
If you want to return an instance of your class (this), it does simply by using the class declaration (Test<T>):
public Test<T> setField() {
return this;
}
If you want to return a type of a generic parameter, look at #wero's answer.
Casting this to T makes only sense if you use a recursive type bound. Still you need to add a cast and suppress the warning:
abstract class Test<T extends Test<T>> {
#SuppressWarnings("unchecked")
public T setField()
{
return (T)this;
}
}
Define derived classes like:
public class DerivedTest extends Test<DerivedTest> { ... }
and now this works without any casts needed in the client code:
DerivedTest d = new DerivedTest().setField();
It is not possible for something like this to work safely in general in Java. this is only known to be an instance of Test<T>, which is not known to be a subtype of T, the type you want to return. There is no bound on T that can guarantee that this is an instance of T. No matter what bounds you give T, for any type that you can use for T that satisfies those bounds (call it X), I can just define a new class (unrelated to X) that extends Test<X>, and you cannot return an instance of this class as X, because it is not an X.

Is there any way to define a generic method in a super class to reference the inheriting class's type?

When defining something like this method:
class State {
public void addOperator(Operator<? extends State> op) {
}
}
Is there any way to define it in this way:
class State {
public void addOperator(Operator<? extends this.getClass()> op) {
}
}
So that any class inherting from State forces all passed in value to conform to its class-type.
I know that the above wont work, but is there anyway to force a generic wild-card to at least match the current classes type?
You already accepted an answer that claims your desired constraint can't be expressed in Java. If I understand the requirements correctly, the following solution comes close.
// You didn't flesh out what an operator does or provides,
// so I'll just make something up.
interface Operator<T> {
void apply(T arg);
}
// Request that a derived type provide its own type as a type
// parameter, per the Curiously Recurring Template Pattern (CRTP).
abstract class State<T extends State> {
public void addOperator(Operator<? extends T> op) {
final PrintStream s = System.out;
s.print("Received an operator of concrete type ");
s.print(op.getClass().getName());
s.println('.');
}
}
final class DerivedState extends State<DerivedState> {
}
public class Driver {
public static void main(String[] args) {
DerivedState ds = new DerivedState();
ds.addOperator(new Operator<DerivedState>() {
// ...
});
// And the following will not compile:
ds.addOperator(new Operator<Integer>() { /* ... */ });
}
}
Note that DerivedType's apply() method will only accept an Operator argument whose type parameter is DerivedType—or some type derived from DerivedType, but since DerivedType is final, no other such types exist.
What we can't do—which may be what Chris was alluding to—is mandate that the type parameter provided to State is in fact the derived type itself. We can't prevent the following definition, where one class supplies another as the type parameter for State:
final class AnotherDerivedState extends State<DerivedState> {
}
Here, one could call AnotherDerivedState#addOperator() with an Operator<DerivedState>, which is obviously not of type Operator<AnotherDerivedState>.
You can't prevent someone from deriving from State "incorrectly", but if you assume that people will follow the intended derivation pattern, you can help them use the rest of your library safely.
A subclass can be used instead of the superclass at any time because of the inclusion polymorphism.
Try writing
State.class
to get the Class object of State.
class State {
public void addOperator(Operator<? extends State.class> op) {
}
}
Although I am not sure that Class object inherit among them, they use generics, Class<T>.
So let's say we have class Base, and class Derived extends Base.
Class<Derived> probably does extends Class<Base>.
Instead, this scenario looks more promising
class State {
public void addOperator(Operator<Class<? extends State>> op) {
}
}

How to return a subclass of parameterized return type whose parametric type is a subclass of the return type's parametric type?

The title sounds a bit complicated, but in fact the question is quite simple.
I have the following method:
AbstractClassA<AbstractClassB> myMethod() {...}
And I want to invoke it like this:
ClassAImpl<ClassBImpl> result = myMethod();
The problem is that no matter what I tried, I ended up with unchecked cast warning or compiler error.
What is the right way of doing it?
It all depends. The simplest answer is that you're just going to need to cast the results of myMethod to the same type as result. Suppose we take all the generics out of the problem, like this:
public class Demo {
private abstract class AbstractClassA {}
private class ClassAImpl extends AbstractClassA {}
private abstract class AbstractClassB {}
private class ClassBImpl extends AbstractClassB {}
Demo() {
ClassAImpl result = myMethod();
}
public AbstractClassA myMethod() {
return new ClassAImpl();
}
public static void main(String[] args) {
new Demo();
}
}
The call to myMethod is still a compiler error, because the types don't match. A good way to think about this is to imagine that you don't know anything about the code in the body of myMethod. How would you know that it's returning a ClassAImpl and not some other subtype of AbstractClassA? So to make it work, you'd need to invoke myMethod like this:
ClassAImpl result = (ClassAImpl)myMethod()
As for the generics bit, you probably want your method signature to be something like:
public AbstractClassA<? extends AbstractClassB> myMethod()
but maybe want something like:
public AbstractClassA<ClassBImpl> myMethod()
or even:
public ClassAImpl<ClassBImpl> myMethod()
All except the last are going to require some explicit casting.
Why on earth would you do something like that anyway? Methinks either your design is wrong or you are leaving out some important information. If myMethod is in the same class as the attempted call, so that your caller is privy to information about how the method is implemented, you should create a private myMethodAux that returns the more specific type. You are probably still going to run into variance problems, however, as ClassAImpl<ClassBImpl> is not a subclass of AbstractClassA<AbstractClassB>. It is a subclass of AbstractClassA<? extends AbstractClassB>.
Your comment above seems to indicate that you were not aware of this variance restriction on the subtyping relation in Java.
You can't assign a super type into sub type without explicit type casting.
Use instanceof operator before down casting.
Try Class#isInstance()
abstract class AbstractClassA<T extends AbstractClassB> {}
abstract class AbstractClassB {}
class ClassAImpl<T extends AbstractClassB> extends AbstractClassA<T> {}
class ClassBImpl extends AbstractClassB {}
...
public static AbstractClassA<? extends AbstractClassB> myMethod() {
return new ClassAImpl<ClassBImpl>();
}
...
AbstractClassA<? extends AbstractClassB> returnValue=myMethod();
if(returnValue.getClass().isInstance(new ClassAImpl<ClassBImpl>())){
ClassAImpl<ClassBImpl> result=(ClassAImpl<ClassBImpl>)returnValue;
...
}

Java - Overriding return type of extended interface when return type uses generics for own method parameter types

i've stumbled upon a curiosity in the java inheritance, and I wanted you to ask for better ideas on that:
Assume two interfaces A and A1
Interface A1 extends A
Interface A has a method which returns a generic type.
The generic type would be like GenericType<T>.
A basic idea is now to change this generic return type from
GenericType<Object> in Interface A into
GenericType<String> in Interface A1
Well seems to be easy at first (bad things will come later on)
We declare Interface A like
public interface InterfaceA {
public GenericType<? extends Object> getAGenericType();
}
and Interface A1 like
public interface InterfaceA1 extends InterfaceA
{
#Override
public GenericType<String> getAGenericType();
}
As you see we are forced to write GenericType<? extends Object> in Interface A itself to allow overriding it with generic based "subclasses".
(In fact the generic parameter of the generictype is subclassed not the generic type itself)
Now assume the GenericType has its own method looking like:
public interface GenericType<D>
{
public void doSomethingWith( D something );
}
Now trying to instantiate A1 works great.
Rather trying to instantiate A will suck. To see why look at this "use the interface" class:
public class LookAtTheInstance
{
#SuppressWarnings("null")
public static void method()
{
InterfaceA a = null;
InterfaceA1 a1 = null;
GenericType<String> aGenericType = a1.getAGenericType();
GenericType<? extends Object> aGenericType2 = a.getAGenericType();
Object something = null;
aGenericType2.doSomethingWith( something );
}
}
You ask: "And now?"
It does not work on the last lines. In fact the parameter "something" is not even from type "Object" it is from Type "? extends Object". So you cannot pass the declared "Object" type. You can't pass anything at all.
So you end up declaring nice interfaces which, as it turns out, cannot be instantiated right.
Do you have ideas how to model such a use case, where the subclasses will have to override the return type, while the return type is a generics?
Or how would you go around such a model case?
Or am I just missing a simple point in the generic declaration and my example is possible this way?
----------- (1) edit due to answers -----------
A very good basic idea is making the interface A more abstract! I had exactly the same idea first, but... (this has to come)
Assume doing this:
We introduce a new interface AGeneric
public interface InterfaceAGeneric<T>{
public GenericType<T> getAGenericType();
}
Now we will have to extend A and A1 from this new interface:
public interface InterfaceA extends InterfaceAGeneric<Object>{}
public interface InterfaceA1 extends InterfaceAGeneric<String>{}
That works fine, althought it breaks the path of the original inheritance.
If we want A1 still be extendable from A, we have to change A1 to
public interface InterfaceA1 extends InterfaceA, InterfaceAGeneric<String>{}
and there a problem is again. This does not work, since we extend indirectly the same interface with different generic types. This is unfortunately not allowed.
You see the problem?
-
And to point to another circumstance:
If you cast the GenericType<? extends Object> to GenericType<Object> it obviously works.
Example:
public class LookAtTheInstance
{
public static void main( String[] args )
{
InterfaceA a = new InterfaceA()
{
#Override
public GenericType<? extends Object> getAGenericType()
{
return new GenericType<Object>()
{
#Override
public void doSomethingWith( Object something )
{
System.out.println( something );
}
};
}
};
;
#SuppressWarnings("unchecked")
GenericType<Object> aGenericType2 = (GenericType<Object>) a.getAGenericType();
Object something = "test";
aGenericType2.doSomethingWith( something );
}
}
So it seems for me that the resolving of the parameter type of the method
public interface GenericType<D extends Object>
{
public void doSomethingWith( D something );
}
is wrong.
If D is unified with "? extends Object" why the parameter type is not forced to be "Object"?
Wouldnt this make more sence?
A basic idea is now to change this generic return type from GenericType in Interface A into GenericType in Interface A1
This is not possible, because Java Generics are invariant. [1]
As you found out, you cannot have an interface declaring a method that returns GenericType<Object> and in a sub interface override the method to return GenericType<String>: The latter return type is not a subtype of the former. And for good reason!
You tried to
extend indirectly the same interface with different generic types. This is unfortunately not allowed.
There is no way this could possibly work: E.g. what should be the type of E in public E set(int index, E element) in a class that implemented both List<String> and List<Object>? Your subclassed interface would have to produce a similar hybrid: The return value of getAGenericType in the sub interface would have to implement both the GenericType<String> and the GenericType<Object> interface. And as we saw, this is impossible.
The compiler does not know what you are going to do with the type parameter in GenericType (although it theoretically could find out, it doesn't). If you had a variable of type GenericType<String> and assigned a GenericType<Object> to it, you may very well end up putting a Long instance where a String is expected, and get a ClassCastException where you won't expect one.
In the doSomethingWith method of your variable GenericType<? extends Object> aGenericType2 you can pass one thing: null. null is the only object reference that has a subtype of ? extends Object. The lower bound type of ? extends Object is the null type, which cannot be expressed in Java, and only implicitly exists as the type of the null reference.
[1] http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29#Java
I don't know if this is what you are expecting, but you can declare your interface something like:
public interface Interface <K extends Object> { ... }
While your class might look like:
public class InterfaceImpl implements Interface<String> { ... }
#Override annotation:
When overriding a method, you might
want to use the #Override annotation
that instructs the compiler that you
intend to override a method in the
superclass. If, for some reason, the
compiler detects that the method does
not exist in one of the superclasses,
it will generate an error.
With this annotation you cannot change return type of function.
If you want to override return type, just make interface A more abstract, add generic to this interface:
public interface InterfaceA<T> {
public GenericType<T> getAGenericType();
}
Sample about overriding a generic method in a generic class.
The trouble is that InterfaceA doesn't know what type it's holding. If you get InterfaceA to take a generic argument then you could do this:
public interface InterfaceA<T>
{
public GenericType<T> getAGenericType();
}
public interface InterfaceA1 extends InterfaceA<String>
{
#Override
public GenericType<String> getAGenericType();
}
public class LookAtTheInstance
{
#SuppressWarnings("null")
public static void method()
{
InterfaceA<String> a = null;
InterfaceA1 a1 = null;
GenericType<String> aGenericType = a1.getAGenericType();
GenericType<String> aGenericType2 = a.getAGenericType();
String something = null;
aGenericType2.doSomethingWith( something );
}
}
I'm several years late to the party, but I found this page while searching for a related question and none of the answers really hit on the central issue, which I think is worth clarifying. Let's look at a slightly-more-fleshed-out example:
interface GenericType<D> {
D getAValue();
void doSomethingWith(D value);
}
class StringType implements GenericType<String> {
#Override
public String getAValue() {
return "Hello World";
}
#Override
public void doSomethingWith(final String value) {
System.out.println(value.length());
}
}
interface InterfaceA {
GenericType<? extends Object> getAGenericType();
}
interface InterfaceA1 extends InterfaceA {
#Override
GenericType<String> getAGenericType();
}
class AnActualA1 implements InterfaceA1 {
#Override
public GenericType<String> getAGenericType() {
return new StringType();
}
}
class LookAtTheInstance {
public static void method() {
InterfaceA1 a1 = new AnActualA1();
// 'g1' is a StringType, which implements GenericType<String>; yay!
GenericType<String> g1 = a1.getAGenericType();
// Everything here is fine.
String value = g1.getAValue();
g1.doSomethingWith("Hello World");
// But if we upcast to InterfaceA???
InterfaceA a = (InterfaceA) a1;
// Note: a.getAGenericType() still returns a new StringType instance,
// which is-a GenericType<? extends Object>.
GenricType<? extends Object> g = a.getAGenericType();
// StringType.getAValue() returns a String, which is-an Object; yay!
Object object = g.getAValue();
// StringType.doSomethingWith() method requires a String as the parameter,
// so it is ILLEGAL for us to pass it anything that cannot be cast to a
// String. Java (correctly) prevents you from doing so.
g.doSomethingWith(new Object()); // Compiler error!
}
}
Conceptually, GenericType is NOT a GenericType, since a GenericType can only doSomethingWith() Strings, while a GenericType needs to be able to doSomethingWith() any object. GenericType is a compromise which the compiler allows you to use as a "base class" for any GenericType where D is-an Object, but only allows you to use a reference of that type to call methods that are type-safe for any possible runtime value of '?' (such as getAValue(), whose return value can always be safely cast to an Object since D is-an Object regardless of runtime type).
It's hard to tell what (if anything) the original poster was actually trying to model with this code, and in particular how much of the generic-ness of GenericType was really needed, but perhaps the inheritance should have gone the other way around?
/**
* I can do something with instances of one particular type and one particular
* type only.
*/
interface GenericType<D> {
void doSomethingWith(D value);
}
/**
* I can do something with instances of any type: I am-a GenericType<String>
* because I can totally do something with a String (or any other kind of
* Object).
*/
interface NonGenericType extends GenericType<Object>, GenericType<String> {
#Override
void doSomethingWith(Object value);
}
interface StringHandlerFactory { // nee InterfaceA1
GenericType<String> getAGenericType();
}
/**
* I extend StringHandlerFactory by returning a NonGenericType (which is-a
* GenericType<String>, satisfying the interface contract, but also so much
* more).
*/
interface ObjectHandlerFactory extends StringHandlerFactory { // nee InterfaceA
#Override
NonGenericType getAGenericType();
}
The downside being that there's no good way to express to the java compiler that NonGenericType extends GenericType, even though conceptually it could in this case, since GenericType never uses D as a return value. You have to manually specify each GenericType that you want it to extend. :(
So you end up declaring nice interfaces which, as it turns out, cannot be instantiated right.
I think that the purpose of InterfaceA is not to be instantiated at all, because one of its dependable classes are generic. That's what you meant declaring:
public GenericType<? extends Object> getAGenericType()

Categories

Resources