Differencebetween 'E', 'T', and '' for Java Generics

Java Generics - difference in method declaration

By writing <R> Stream<R> myFunc(Function<? super T, ? extends R> mapper) you are telling the compiler that:

  • R is any class and is local to the method (by starting with<R> at the beginning)
  • The return type is a Stream of R
  • T is a class specified in the type parameter of MyGenericsTest<T> (if you dont specify it, it wont work as the compiler will not know T)

If you change to Stream<R> myFunc(Function<? super T, ? extends R> mapper), R and T are not local (no <R, T> at the beginning of the method) and the compiler expects them to be defined at a class level as MyGenericsTest<T, R>

When should I use generics to define relationships between types?

A person is generally not parameterized with a type of car. Only very annoying persons are defined by their car. Persons change cars too (in time). So I would not parameterize the class, if only for the semantics.

Think about what you try to mimic from the real world, before going into such programming details.

JAXB Marshalling and Generics

You could write a custom adapter (not using JAXB's XmlAdapter) by doing the following:

1) declare a class which accepts all kinds of elements and has JAXB annotations
and handles them as you wish (in my example I convert everything to String)

@YourJAXBAnnotationsGoHere
public class MyAdapter{

@XmlElement // or @XmlAttribute if you wish
private String content;

public MyAdapter(Object input){
if(input instanceof String){
content = (String)input;
}else if(input instanceof YourFavoriteClass){
content = ((YourFavoriteClass)input).convertSomehowToString();
}else if(input instanceof .....){
content = ((.....)input).convertSomehowToString();
// and so on
}else{
content = input.toString();
}
}
}

// I would suggest to use a Map<Class<?>,IMyObjToStringConverter> ...
// to avoid nasty if-else-instanceof things

2) use this class instead of E in your to-be-marshalled class

NOTES

  • Of course this would not work for complex (nested) data structures.
  • You have to think how to unmarshall this back again, could be more tricky. If
    it's too tricky, wait for a better proposal than mine ;)

Generic which is required to implement two interfaces

you can use Multiple Bounds like <T extends CanFly & CanRun>

Note: in future if you want to add a class along with CanFly & CanRun then make sure to put the class at the beginning like <T extends className & CanFly & CanRun> otherwise it will raise an exception

What is the purpose of generics before return type

This is the syntax that makes your method (as opposed to your class) generic.

Methods of regular and generic classes can be made generic on their own type parameters. In this case, your inspect method is generic on U, which must be a type extending from Number.

Java Generics: FooT, Foo, FoobarT extends FooT and FoobarT extends Foo

class Foo<T> {}

is your class.

Foo yourVariable = new Foo();

equals Foo<Object> yourFoo = new Foo<Object>();

class Foobar<T> extends Foo {}

equals class Foobar<T> extends Foo<Object> {}

the answer to your question

class YourClass<T extends Comparable<T>> {}

means YourClass's type T is able to compare itself to objects of T (its class), whereas

class YourClass<T extends Comparable> {}

's type T is able to compare itself to objects of class Object, which is not what you want

Java Generics & operator

The code you have given is legal, but useless.

It is useless for two reasons:

  1. You have defined a generic type, T, as part of the method declaration that must implement the Enum<T> interface as well as the FunctionalInterface interface. However you haven't then used that type anywhere in the method's signature (i.e. arguments or return type) so it is effectively ignored.

  2. Having an interface implement 'FunctionalInterface' is possible, but certainly not it's intended use. It is designed to be an annotation to an interface, not an interface itself.

You could make this combination work:

public interface Inter {
<T extends Enum<T> & FunctionalInterface> String getString(T value);
}

static class InterImpl implements Inter {
@Override
public <T extends Enum<T> & FunctionalInterface> String getString(T value) {
return value.name();
}
}

enum EnumImpl implements FunctionalInterface {
A, B, C;

@Override
public Class<? extends Annotation> annotationType() {
return null;
}
}

public static void main(String[] args) {
InterImpl impl = new InterImpl();
System.out.println(impl.getString(EnumImpl.B));
}

You'll see that the EnumImpl enumeration implemements Enum and FunctionalInterface so it can be used as an argument to getString.

So that's an explanation but, frankly, I can't think of any useful use case for such a piece of code.

why type variable is non-reifiable type in java

The docs state that

A non-reifiable type does not have all of its information available at runtime.

The type of T at runtime is Object so information is lost. An example of the information that is lost is how an object can be created. Consider this class:

public class A {
private int a;
public A() {
a = 5;
}
}

Now look at this not compiling code:

public class Generic<T> {
T foo() {
return new T(); //Compiler Error!
}
}

If this was allowed and you were instantiating a Generic<A> g = new Generic<>(); and calling g.foo(), the constructor of T could not be called, because, at runtime, T is only known as Object. Therefore, an valid instance of A cannot be created and returned. You even cannot be sure which information a constructor of T needs. The information how T can be constructed is lost.

That is one reason why type parameters must be non-reifiable types.



Related Topics



Leave a reply



Submit