java generics runtime type - java

A post I found by Ian Robertson has a great utility method for determining the runtime class for a Java class type parameter. It goes a few steps beyond the quick version:
ParameterizedType pt = (ParameterizedType)this.getClass().getGenericSuperclass();
Class<?> c = (Class<?>) pt.getActualTypeArguments()[0]
Either method works like a charm for parameterized children inheriting from an abstract parameterized parent (class Foo<T> extends Bar<T>), or an anonymous instance of a parameterized abstract class (new Foo<Bar>() {}), and instantiated with a concrete type.
Where I fail is in trying to do the same for some other object instantiated via type parameter. Relevant class objects are:
public class Foo {/* code omitted for brevity */}
public class MyFoo extends Foo {/* code omitted for brevity */}
public abstract class AbstractLoader<T extends Foo> {/* code omitted for brevity */}
public abstract class AbstractReader<T extends Foo> {/* code omitted for brevity */}
public class MyReader<T extends Foo> extends AbstractReader<T> {/* code omitted for brevity */}
public class Loader<T extends Foo> extends AbstractLoader<T> {
/* code omitted for brevity */
public MyReader<T> getReader() {
// Parameterized type "T" doesn't seem to carry through here
return new MyReader<T>();
}
}
Sample Code:
static void main(String... s) {
Loader<MyFoo> loader = new Loader<>(); // new Loader<MyFoo>() for Java < 1.7
MyReader<MyFoo> = loader.getReader();
ParameterizedType pt = (ParameterizedType)loader.getClass().getGenericSuperclass();
System.out.println("LoaderType = " + pt.getActualTypeArguments()[0]);
// Prints: LoaderType = MyFoo
pt = (ParameterizedType)reader.getClass().getGenericSuperclass();
System.out.println("ReaderType = " + pt.getActualTypeArguments()[0]);
// Prints: ReaderType = T
}
Intuition tells me this "should" be possible somehow, but I can't seem to discover the right answer. OTOH, this may be another example of "can't do that" due to type erasure.

You are completely misunderstanding something. There is NO DIFFERENCE between new Loader();, new Loader<Integer>();, and new Loader<Object>();, etc. at runtime. It is impossible to tell them apart. Get that notion out of your head right now.
If we create a class, then the types (including generics) in the declarations about that class, including superclass, method types, field types, etc. are stored in the class file. This information can be retrieved at runtime.
So when you have new Foo<Bar>() {}, that creates an instance of a certain class (an anonymous class) which extends a generic type with a specific type parameter. It's similar to:
class SomeAnonymousClass extends Foo<Bar> {
}
new SomeAnonymousClass()
The fact that Foo<Bar> is hard-coded at compile-time as the superclass of this class, this is retrievable at runtime.
But your code is doing nothing of this sort. You did not make any subclasses of Loader.

You cannot find type parameter for an object - it is erased at run time.
If you could, then Loader loader0, Loader<MyFoo> loader1, and Loader<MyBar> loader2 would give different results. This difference has to be represented in runtime somehow: either in objects directly, or by referencing different classes. The first variant require additional memory for each instance and was considered unappropriate. The second requires creating classes at runtime, as class Loader itself cannot contain all possible variants of parameterized class Loader - they are unknown at compile time.

Related

Cannot override method that takes in parameter of inner class of generic

Ok, I'll try to explain this as cleanly as I can.
I've created a generic abstract controller class that has a method hasCreatePermissions that looks something like this:
public abstract class ApplicationController<
AppEntity extends ApplicationEntity,
AppService extends ApplicationService<AppEntity>,
DTOManager extends ApplicationDTOManager
> {
// Other methods, properties, etc...
public boolean hasCreatePermissions(DTOManager.CreationRequest requestBody, Optional<UUID> requestingUser) {
return false;
}
}
Essentially, I want any class that overrides this method to be able to use its own DTOManager class as the parameter when it overrides this method.
The generic ApplicationDTOManager class looks like
public abstract class ApplicationDTOManager {
public abstract class CreationRequest {}
public abstract class CreationResponse {}
}
and any class that inherits ApplicationDTOManager can add classes that extend CreationRequest and CreationResponse for their own implementation of respective DTOs.
However, lets say I try to extend it with a UserResource class (assume UserDTOManager exists with an implementation for CreationRequest):
#RestController
public class UserResource extends ApplicationController<
User,
UserService<User>,
UserDTOManager
> {
#Override
public boolean hasCreatePermissions(UserDTOManager.CreationRequest requestBody, Optional<UUID> requestingUser) {
// Stuff
}
}
I'm told that this does not override any super class methods. Why? Is there any way to achieve this as I did not want to pass too many generics to my ApplicationController class, but also cannot have a constructor.
class ApplicationController<
AppEntity extends ApplicationEntity,
No, stop right there. This is declaring a type variable with the bound rules: "Must be either ApplicationEntity or any subtype thereof" and you named it AppEntity. This is going to make your head go in circles when you read the code later, 'I keep confusing reified types with type variables' comprises 95% of all confusion about generics. I know it seems unreadable, but there really is just only one way to go about it, and that is to use single capital letters for all your type vars. So let's fix that right now:
public abstract class ApplicationController<
E extends ApplicationEntity,
S extends ApplicationService<E>,
M extends ApplicationDTOManager> {
Which then immediately lets us see a big problem in the next line:
public boolean hasCreatePermissions(M.CreationRequest requestBody) {}
Of course that can't work. M is a type variable, at compile time the compiler has no idea what type it is. It could be bound to some type that doesn't even exist yet right now. You can't ask for a reified inner type on a type variable. You can of course simply talk about ApplicationDTOManager.CreationRequest and that's presumably what you want.
Alternatively, you're thinking that subtypes of ApplicationDTOManager may also want to subclass ApplicationDTOManager.CreationRequest. This is possible, but then all ApplicationDTOManager types need to carry their associated CreationRequest type as a type variable. We thus fix a few things:
public class ApplicationDTOManager<R extends ApplicationDTOManager.CreationRequest> {
public static class CreationRequest {}
}
You may have a non-static inner class named CreationRequest. I'm going to stop you again on that - non-static inners have an invisible inner field of their outer's type, and combining that invisible voodoo magic with generics just doesn't work. Don't do it. You can explicitly make that field if you must have it, and make a constructor that takes it. This is what javac generates for you if you don't add static to your inner classes. But by making it explicit, you take control of the generics, which you have to here, and avoid confusion which given the nature of the question seems pertinent.
I'm told that this does not override any super class methods. Why?
Java's method names include all their erased types. The name of this method:
class List<T extends Number> {
int hello(String name, boolean[] hi, T arg) throws SQLException {}
}
is, as far as the JVM is concerned, hello(Ljava/lang/String;[ZLjava/lang/Number;)I.
Yeah, no, really. javap -c -v a class file and you'll see it. (I is integer, [ is array, Z is boolean, and Ltxt; encodes ref type names in JVM style, e.g. with slashes and dollars instead of dots). It's written name(params)ret.
If you then subtype something and introduce a method whose erased JVM name is identical, you're overriding. If you don't, it is not an override. Merely an overload. Overrides are dynamically dispatched. But overloads are not - The names are all linked up at compile time. However, for any given 'JVM method name', the lookup is done dynamically based on the receiver type. In other words:
class Fruit {
void hi(Fruit f) { System.out.println("Fruit Fruit"); }
void hi(Apple a) { System.out.println("Fruit Apple"); }
}
class Apple extends Fruit {
void hi(Fruit f) { System.out.println("Apple Fruit"); }
void hi(Apple a) { System.out.println("Apple Apple"); }
}
Fruit f = new Fruit();
Fruit a = new Apple();
a.hi(a);
Will print Apple Fruit. You'd think it should print Apple Apple perhaps - we are calling apple's hi passing an apple, no? But the invocation a.hi(a) is invoking the method named hi(Lfruit;)V (because the type of a is Fruit). The receiver variable (a) has compile time type Fruit, but its real type is Apple. So, which of the hi(Lfruit;)V methods is chosen is done with dynamic dispatch - you get apple's hi(Fruit). Deciding between going with hi(Fruit) and hi(Apple) is done by the compiler only. Given that the type of the expression a is Fruit, you get hi(Fruit). The fact that if you resolve this expression, you get an object whose .getClass() returns Apple.class, doesn't change this.
Hence, what you wrote, does not override. Different name, even if you erase.
Toss generics in the mix and it gets funky. But you can do this.
public abstract class ApplicationDTOManager<I extends CreationRequest, O extends CreationResponse> {
public abstract static class CreationRequest {}
public abstract static class CreationResponse {}
}
public abstract class ApplicationController<
E extends ApplicationEntity,
S extends ApplicationService<AppEntity>,
I extends CreationRequest,
O extends CreationResponse,
M extends ApplicationDTOManager<I, O>
>
// heck that's probably too many, at some point generics aren't worth it
{
public abstract boolean hasCreatePermissions(I requestBody);
}
#RestController
public class UserResource extends ApplicationController<
User,
// UserService<User>, // this seems wrong!
UserService, // UserService should extends ApplicationService<User>
UserDTOManager.CreationRequest,
UserDTOManager.CreationResponse,
UserDTOManager> {
#Override
public boolean hasCreatePermissions(UserDTOManager.CreationRequest requestBody, Optional<UUID> requestingUser) {
// Stuff
}
}
Not sure all this is worth the pain, but, if you insist on linking all this together with generics, the above is the only way. You cannot express the notion 'has an inner type that is a subtype of CreationRequest' is a generics bound.
If you override a method you cannot have a different signature, If the method you override requires a DTOManager.CreateRequest you cannot use a child class within the override method.
You have to "support" all types of input that the parent method could take.
I believe that you need this because the permission validation relies on methods or fields of the child class. If so you should implement it inside the child class.

Generic class with two class hierarchies

I have the following Java generics question
I have the following generic class thay may be sketched as:
public class MyClass<T> {
AnotherClass<T> another;
OtherClass<T> other;
...
}
where ... represents code that is not relevant to the case.
For the class MyClass<T> is not as important which exact type T is (as of now) but for both:
AnotherClass<T>
OtherClass<T>
is absolutely crucial what the generic type is and decisions will be made at runtime in base of that.
Based on that, the type T is not completely arbitrary, it may be either an instance of a hierarchy of classes T_1 or a hierarchy of classes T_2.
As is defined the class, the type T is equivalent to Object but I know that is equivalent to either T_1 or T_2
There is not businnes relation between entities T_1 and T_2 therefore I'm not doing:
public interface BaseT { ... }
public class T_1 implements BaseT { ... }
public class T_2 implements BaseT { ... }
public class MyClass<T extends BaseT>
Clarification about why using a generic if they are unrelated:
I'm defining (trying to) a generic class for both because even they are unrelated explictly, there is a implicit relation because both T_1 and T_2 can and will appear associated to the entity represented in MyClass
T will be the same for MyClass, AnotherClass and OtherClass so that in a instance there will only be either T_1 or T_2 but never both at the same time.
My question is, which alternatives do I have here other than design an
interface for MyClass and implement it for both T_1 and T_2?.
Can I achieve something like MyClass<T extends T_1 or T_2>?
Kind regards
Probably, this is not exactly what your're looking for, but you might give it a try:
Create an abstract generic class that implements everything:
public abstract class MyClass<T>
{
AnotherClass<T> another;
OtherClass<T> other;
// Add any code needed
}
Then create 2 generic classes for both base classes.
These classes may be empty if all code can be implemented in the abstract one:
public class MyT1Class<T extends T_1> extends MyClass<T>
{
}
public class MyT2Class<T extends T_2> extends MyClass<T>
{
}
I know it's not a very good answer but I couldn't leave it as a comment to the question.
You can check the type at runtime by trying the following:
public class MyClass<T>
{
// This factory-method creates an instance of the class if the correct type is passed
// It throws a RuntimeException if not.
public static <T> MyClass<T> getInstance(Class<T> type)
{
if (T_1.class.isAssignableFrom(type) || T_2.class.isAssignableFrom(type))
return (new MyClass<T>());
else
throw new RuntimeException("Cannot create instance of MyClass<" + type.getName() + ">");
}
...
}
Then
class T_3 extends T_2
{
}
....
MyClass<T_3> test_1;
test_1 = MyClass.getInstance(T_3.class); // This will succeed
MyClass<String> test_2;
test_2 = MyClass.getInstance(String.class); // Fails

Proxying with Generics

I use java.lang.reflect.Proxy to proxy objects.
I have this class:
public class TransportableImpl extends Transportable{
public class OrderInvoker extends InvocationHandler{
...
}
}
Here i build the Proxy:
Transportable t = new TransportableImpl();
Order myOrder = new OrderImpl();
Class proxyClass = Proxy.getProxyClass(getClass().getClassLoader(), Transportable.class, Order.class);
Object serializable = proxyClass.getConstructor(new Class[]{InvocationHandler.class}).newInstance(t.new OrderInvoker(myOrder));
Problem is: Class is raw type and
Class<? extends Order & Transportable> proxyClass =
(Class<? extends Order & Transportable>)
Proxy.getProxyClass(getClass().getClassLoader(),
Transportable.class, Order.class);
is hard to read.
Any ideas?
The Proxy#getProxyClass(ClassLoader, Class) method is declared as
public static Class<?> getProxyClass(ClassLoader loader,
Class<?>... interfaces)
Its return type is therefore Class<?>. The normal syntax would be
Class proxyClass<?> = Proxy.getProxyClass(getClass().getClassLoader(), Transportable.class, Order.class);
Technically you could do (with a warning)
public <T extends Order & Transportable> void doSomething() {
Class<T> proxyClass = (Class<T>) Proxy.getProxyClass(Driver.class.getClassLoader(),
Transportable.class, Order.class);
}
but that gains you nothing as you will pretty much never need to use that T variable. The Class class provides very little methods that makes use of it, namely getConstructor(Class...) and newInstance(). But again, the whole point of reflection is that you only know the class types at run time, not at compile time where generics are useful.

what could this generic class declaration could mean?

I know this isn't a good question to ask and I might get cursed to ask it but I cannot find any place to get help on this question
Below is a Generic class that appeared in my interview question (which I have already failed). The question was to tell what this Class declaration is doing and in what circumstances this could be used for ?
I have very limited understanding of Generic programming but I understand that 'T' is Type and 'extends' here means that the Type should have inherited 'SimpleGenericClass' but I do not understand the '?' at the end and in what circumstances this Class could be potentially used for
public abstract class SimpleGenericClass<T extends SimpleGenericClass<?>> {
}
First, because the class SimpleGenericClass is abstract, it is meant to be subclassed.
Second, it is a generic class which means that inside the class somewhere you will almost assuredly be using the generic parameter T as the type of a field.
public abstract class SimpleGenericClass<T...> {
T x;
}
Now the first interesting thing here is that T is bounded. Because it is declared as T extends SimpleGenericClass<?> it can only be SimpleGenericClass<?> or some subclass of SimpleGenericClass<?>. You also asked about thr ?. That's known as a wildcard and there is a pretty good explanation of it at the Java Tutorial on Wildcards. In your case we would say this is a "SimpleGenericClass of unknown." It is needed in Java because SimpleGenericClass<Object> is NOT the superclass of SimpleGenericClass<String>, for example.
The second interesting thing though is that since T is a SimpleGenericClass of some sort, your class is more than likely defining recursive structures. What comes to my mind are trees (think of expression trees) where SimpleGenericClass is the (abstract) node type, designed to be subclassed with all kinds of specialized node types.
UPDATE This SO question on self-bounded generics might be helpful to you.
UPDATE 2
I went ahead and put together some code that illustrates how this can be used. The app doesn't do anything but it does compile and it shows you how the generic bounds can supply some possibly-meaningful constraints.
public abstract class Node<T extends Node<?>> {
public abstract T[] getChildren();
}
class NumberNode extends Node {
int data;
public Node[] getChildren() {return new Node[]{};}
}
class IdentifierNode extends Node {
int data;
public Node[] getChildren() {return new Node[]{};}
}
class PlusNode extends Node {
NumberNode left;
NumberNode right;
public NumberNode[] getChildren() {return new NumberNode[]{};}
}
The nice thing here is that NumberNode[] is a valid return type for PlusNode.getChildren! Does that matter in practice? No idea, but it is pretty cool. :)
It's not the greatest example, but the question was rather open ended ("what might such a thing be used for?"). There are other ways to define trees, of course.
This really only means that you allow the user of class SimpleGenericClass to parametrize instances of the class with the type T. However, T cannot be any type, but must be a subtype of SampleGenericClass (or SampleGenericClass itself).
In the remainder of the code of class SimpleGenericClass you may use type T in method signatures.
Let's assume for a second that SimpleGenericClass is not abstract. When using it, you could then write:
new SimpleGenericClass<SampleGenericClass<String>>();
I.e. you parametrize SimpleGenericClass with SampleGenericClass and SampleGenericClass with String.
This basically sais: in this class you have a Type placeholder called T, and a restriction on that placeholder, it must be of type SimpleGenericClass or something that extends it. Once you obey that rule you can create instances of your class and give an actual type to T, that later on can be used in methods of that class, something like this:
public class C <T extends Number>{
public void doSomething(T t) {
}
public static void main(String... args) {
//works:
C<Number> c = new C<Number>();
c.doSomething(new Number() {
//Aonimous implementation of number
});
//won't work
//C<Object> c = new C<Object>();
C<Integer> c2 = new C<Integer>();
c2.doSomething(new Integer(1));
//won't work
//c2.doSomething(new Number() {
//Aonimous implementation of number
//});
}
}
The SimpleGenericClass<?> is pretty redundant at this point. If another generic type is needed on this class, you can have more than one (SimpleGenericClass<T extends SimpleGenericClass, T2 extends Whatever>)
By definition it says that the SimpleGenericClass can work on a type <T> which is subclass of SimpleGenericClass.
So I assume there will be some operations which will work on <T>.
Now to see why one would define a template like this - (not much I can think of , really ) may be a scenario where the SimpleGenericClass is an abstract class (just realized it is as per OP :P) and expects that it can work on any concrete classes ?
Guys what do you think ?
I guess you have got the question in this form (T instead of ?):
public abstract class SimpleGenericClass<T extends SimpleGenericClass<T>>
Take a look at this code:
abstract class Foo<SubClassOfFoo extends Foo<SubClassOfFoo>>
{
/** subclasses are forced to return themselves from this method */
public abstract SubClassOfFoo subclassAwareDeepCopy();
}
class Bar extends Foo<Bar> {
public Bar subclassAwareDeepCopy() {
Bar b = new Bar();
// ...
return b;
}
}
Bar b = new Bar();
Foo<Bar> f = b;
Bar b2 = b.subclassAwareDeepCopy();
Bar b3 = f.subclassAwareDeepCopy(); // no need to cast, return type is Bar
The trick going on with Foo<SubClassOfFoo extends Foo<SubClassOfFoo>> is:
Any subclass of Foo must supply a type argument to Foo.
That type argument must actually be a subclass of Foo.
Subclasses of Foo (like Bar) follow the idiom that the type
argument they supply to Foo is themselves.
Foo has a method that returns SubClassOfFoo. Combined
with the above idiom, this allows Foo to formulate a contract that
says “any subclass of me must implement subclassAwareDeepCopy() and
they must declare that it returns that actual subclass“.
To say that another way: this idiom allows a superclass (such as an Abstract Factory) to define methods whose argument types and return types are in terms of the subclass type, not the superclass type.
The trick is done for example in Enum JDK class:
public abstract class Enum<E extends Enum<E>>
Refer here for more details.

Compile error on inheritance of generic inner class extending with bounds

I have a problem when compiling a generic class with an inner class. The class extends a generic class, the inner class also.
Here the interface implemented:
public interface IndexIterator<Element>
extends Iterator<Element>
{
...
}
The generic super class:
public abstract class CompoundCollection<Element, Part extends Collection<Element>>
implements Collection<Element>
{
...
protected class CompoundIterator<Iter extends Iterator<Element>>
implements Iterator<Element>
{
...
}
}
The generic subclass with the compiler error:
public class CompoundList<Element>
extends CompoundCollection<Element, List<Element>>
implements List<Element>
{
...
private class CompoundIndexIterator
extends CompoundIterator<IndexIterator<Element>>
implements IndexIterator<Element>
{
...
}
}
The error is:
type parameter diergo.collect.IndexIterator<Element> is not within its bound
extends CompoundIterator<IndexIterator<Element>>
^
What is wrong? The code compiles with eclipse, but not with java 5 compiler (I use ant with java 5 on a mac and eclipse 3.5). No, I cannot convert it to a static inner class.
The Java Language Specification, §8.1.3, defines the semantics of subclassing inner types as follows:
Furthermore, for every superclass S of
C which is itself a direct inner class
of a class SO, there is an instance of
SO associated with i, known as the
immediately enclosing instance of i
with respect to S. The immediately
enclosing instance of an object with
respect to its class' direct
superclass, if any, is determined when
the superclass constructor is invoked
via an explicit constructor invocation
statement.
Note that the enclosing instance is only described to be of a particular class, not a particular type. As all instances of a generic type share the same class, the following code would be legal:
class Base<E> {
E e;
protected class BaseInner<I extends E>{
E e() { return e; }
}
}
class StrangeSub extends Base<Integer> {
protected class StrangeSubInner extends Base<String>.BaseInner<String> {}
}
Of course, this can be used to break the type invariant (i.e. cause heap pollution):
StrangeSub ss = new StrangeSub();
ss.e = 42;
String s = ss.new StrangeSubInner().e();
The eclipse compiler takes the Java Language Specification as face value, and accepts the above code without even emitting an "unchecked" warning. While arguably technically compliant with the JLS, this clearly violates its intent.
The Sun Java Compiler rejects the declaration of StrangeSubInner with:
Test.java:32: type parameter java.lang.String is not within its bound
protected class StrangeSubInner extends Base<String>.BaseInner<String> {}
^
Apparently the compiler didn't simply check the type parameter against inner's super class' type parameter bound like eclipse did. In this case, I believe this the right thing to do, as the declaration is clearly unsafe. However, the Sun compiler equally rejects the following declaration, even though it is provably type safe:
class StrangeSub extends Base<Integer> {
protected class StrangeSubInner extends BaseInner<Integer> {}
}
My hunch is that verifying the consistency of this diamond-shaped type restrictions is beyond the capabilities of the Sun compiler, and such constructs are therefore summarily rejected instead.
To work around this limitation, I'd first try to get rid of the type parameter to CompoundIterator.
Maybe this is not much progress, but I managed to reduce the above code to the following code that still exhibits the same weird behavior:
class Base<E> {
protected class BaseInner<I extends E>{
}
}
class Sub<E> extends Base<E>{
class SubInner extends BaseInner<E> {
}
}

Categories

Resources