Jackson: programmatically determine subtypes - java

Given an arbitrary Class object, what is the best way to determine the subtypes of that class registered with Jackson?
For example, here's a simple case where classes Lion and Penguin are subtypes of Animal:
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
#JsonSubTypes({
#JsonSubTypes.Type(Lion.class),
#JsonSubTypes.Type(Penguin.class)})
public static abstract class Animal {}
#JsonTypeName("Lion")
public static class Lion extends Animal {}
#JsonTypeName("Penguin")
public static class Penguin extends Animal {}
My dream function would look like:
List<Class> getSubTypeClasses(Class c) {...}
where getSubTypeClasses(Animal.class) would return Lion and Penguin.
If the Jackson API doesn't provide a convenient way to get this information I will read the annotations manually, but it would be nice to know of a technique compatible with any AnnotationIntrospector implementation.

Instead of ai.findSubTypes(ac) you may use mapper.getSubtypeResolver().collectAndResolveSubtypes(ac, config, ai).
I've not tested it with registered subtypes but looking at the code it should work.

There is currently no mechanism for doing that. But you could file a request for adding something like this: given a base class, return a set of known sub-types along with type ids used for them, and the default implementation use. This seems like a reasonable thing to provide access for.
In the meantime (new feature could be available for 2.3, so it'd take some time), have a look at AnnotationIntrospector and see what methdods are available there, and how jackson-databind uses it to build mapping information. You should not have to write all of that manually, even without accessor.

Thanks to StaxMan for nudging me in the right direction. Here's a solution for Jaxen 2.2.3:
public static List<Class> getSubtypeClasses(ObjectMapper mapper, Class c) {
return getSubtypeClasses(mapper.getDeserializationConfig(), c);
}
public static List<Class> getSubtypeClasses(MapperConfig config, Class c) {
AnnotationIntrospector ai = config.getAnnotationIntrospector();
AnnotatedClass ac = AnnotatedClass.constructWithoutSuperTypes(c, ai, config);
List<NamedType> subtypes = ai.findSubtypes(ac);
List<Class> result = new ArrayList<>();
if (subtypes != null) {
for (NamedType subtype : subtypes) {
result.add(subtype.getType());
}
}
return result;
}

To access the SubTypes annotations of a super class you can use the JacksonAnnotationIntrospector:
AnnotationIntrospector annotationInspector = new JacksonAnnotationIntrospector();
JavaType superClassType = TypeFactory.defaultInstance().uncheckedSimpleType(Animal.class);
AnnotatedClass annotatedClass = AnnotatedClass.construct(superClassType,new ObjectMapper().getSerializationConfig());
List<NamedType> subtypes = annotationInspector.findSubtypes(annotatedClass);

Related

discover interface classes at runtime [duplicate]

I want to do something like this:
List<Animal> animals = new ArrayList<Animal>();
for( Class c: list_of_all_classes_available_to_my_app() )
if (c is Animal)
animals.add( new c() );
So, I want to look at all of the classes in my application's universe, and when I find one that descends from Animal, I want to create a new object of that type and add it to the list. This allows me to add functionality without having to update a list of things. I can avoid the following:
List<Animal> animals = new ArrayList<Animal>();
animals.add( new Dog() );
animals.add( new Cat() );
animals.add( new Donkey() );
...
With the above approach, I can simply create a new class that extends Animal and it'll get picked up automatically.
UPDATE: 10/16/2008 9:00 a.m. Pacific Standard Time:
This question has generated a lot of great responses -- thank you. From the responses and my research, I've found that what I really want to do is just not possible under Java. There are approaches, such as ddimitrov's ServiceLoader mechanism that can work -- but they are very heavy for what I want, and I believe I simply move the problem from Java code to an external configuration file. Update 5/10/19 (11 years later!) There are now several libraries that can help with this according to #IvanNik's answer org.reflections looks good. Also ClassGraph from #Luke Hutchison's answer looks interesting. There are several more possibilities in the answers as well.
Another way to state what I want: a static function in my Animal class finds and instantiates all classes that inherit from Animal -- without any further configuration/coding. If I have to configure, I might as well just instantiate them in the Animal class anyway. I understand that because a Java program is just a loose federation of .class files that that's just the way it is.
Interestingly, it seems this is fairly trivial in C#.
I use org.reflections:
Reflections reflections = new Reflections("com.mycompany");
Set<Class<? extends MyInterface>> classes = reflections.getSubTypesOf(MyInterface.class);
Another example:
public static void main(String[] args) throws IllegalAccessException, InstantiationException {
Reflections reflections = new Reflections("java.util");
Set<Class<? extends List>> classes = reflections.getSubTypesOf(java.util.List.class);
for (Class<? extends List> aClass : classes) {
System.out.println(aClass.getName());
if(aClass == ArrayList.class) {
List list = aClass.newInstance();
list.add("test");
System.out.println(list.getClass().getName() + ": " + list.size());
}
}
}
The Java way to do what you want is to use the ServiceLoader mechanism.
Also many people roll their own by having a file in a well known classpath location (i.e. /META-INF/services/myplugin.properties) and then using ClassLoader.getResources() to enumerate all files with this name from all jars. This allows each jar to export its own providers and you can instantiate them by reflection using Class.forName()
Think about this from an aspect-oriented point of view; what you want to do, really, is know all the classes at runtime that HAVE extended the Animal class. (I think that's a slightly more accurate description of your problem than your title; otherwise, I don't think you have a runtime question.)
So what I think you want is to create a constructor of your base class (Animal) which adds to your static array (I prefer ArrayLists, myself, but to each their own) the type of the current Class which is being instantiated.
So, roughly;
public abstract class Animal
{
private static ArrayList<Class> instantiatedDerivedTypes;
public Animal() {
Class derivedClass = this.getClass();
if (!instantiatedDerivedClass.contains(derivedClass)) {
instantiatedDerivedClass.Add(derivedClass);
}
}
Of course, you'll need a static constructor on Animal to initialize instantiatedDerivedClass... I think this'll do what you probably want. Note that this is execution-path dependent; if you have a Dog class that derives from Animal that never gets invoked, you won't have it in your Animal Class list.
Unfortunately this isn't entirely possible as the ClassLoader won't tell you what classes are available. You can, however, get fairly close doing something like this:
for (String classpathEntry : System.getProperty("java.class.path").split(System.getProperty("path.separator"))) {
if (classpathEntry.endsWith(".jar")) {
File jar = new File(classpathEntry);
JarInputStream is = new JarInputStream(new FileInputStream(jar));
JarEntry entry;
while( (entry = is.getNextJarEntry()) != null) {
if(entry.getName().endsWith(".class")) {
// Class.forName(entry.getName()) and check
// for implementation of the interface
}
}
}
}
Edit: johnstok is correct (in the comments) that this only works for standalone Java applications, and won't work under an application server.
The most robust mechanism for listing all subclasses of a given class is currently ClassGraph, because it handles the widest possible array of classpath specification mechanisms, including the new JPMS module system. (I am the author.)
List<Class<Animal>> animals;
try (ScanResult scanResult = new ClassGraph().whitelistPackages("com.zoo.animals")
.enableClassInfo().scan()) {
animals = scanResult
.getSubclasses(Animal.class.getName())
.loadClasses(Animal.class);
}
You could use ResolverUtil (raw source) from the Stripes Framework
if you need something simple and quick without refactoring any existing code.
Here's a simple example not having loaded any of the classes:
package test;
import java.util.Set;
import net.sourceforge.stripes.util.ResolverUtil;
public class BaseClassTest {
public static void main(String[] args) throws Exception {
ResolverUtil<Animal> resolver = new ResolverUtil<Animal>();
resolver.findImplementations(Animal.class, "test");
Set<Class<? extends Animal>> classes = resolver.getClasses();
for (Class<? extends Animal> clazz : classes) {
System.out.println(clazz);
}
}
}
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
class Donkey extends Animal {}
This also works in an application server as well since that's where it was designed to work ;)
The code basically does the following:
iterate over all the resources in the package(s) you specify
keep only the resources ending in .class
Load those classes using ClassLoader#loadClass(String fullyQualifiedName)
Checks if Animal.class.isAssignableFrom(loadedClass);
Java dynamically loads classes, so your universe of classes would be only those that have already been loaded (and not yet unloaded). Perhaps you can do something with a custom class loader that could check the supertypes of each loaded class. I don't think there's an API to query the set of loaded classes.
use this
public static Set<Class> getExtendedClasses(Class superClass)
{
try
{
ResolverUtil resolver = new ResolverUtil();
resolver.findImplementations(superClass, superClass.getPackage().getName());
return resolver.getClasses();
}
catch(Exception e)
{Log.d("Log:", " Err: getExtendedClasses() ");}
return null;
}
getExtendedClasses(Animals.class);
Edit:
library for (ResolverUtil) : Stripes
Thanks all who answered this question.
It seems this is indeed a tough nut to crack. I ended up giving up and creating a static array and getter in my baseclass.
public abstract class Animal{
private static Animal[] animals= null;
public static Animal[] getAnimals(){
if (animals==null){
animals = new Animal[]{
new Dog(),
new Cat(),
new Lion()
};
}
return animals;
}
}
It seems that Java just isn't set up for self-discoverability the way C# is. I suppose the problem is that since a Java app is just a collection of .class files out in a directory / jar file somewhere, the runtime doesn't know about a class until it's referenced. At that time the loader loads it -- what I'm trying to do is discover it before I reference it which is not possible without going out to the file system and looking.
I always like code that can discover itself instead of me having to tell it about itself, but alas this works too.
Thanks again!
Using OpenPojo you can do the following:
String package = "com.mycompany";
List<Animal> animals = new ArrayList<Animal>();
for(PojoClass pojoClass : PojoClassFactory.enumerateClassesByExtendingType(package, Animal.class, null) {
animals.add((Animal) InstanceFactory.getInstance(pojoClass));
}
This is a tough problem and you will need to find out this information using static analysis, its not available easily at runtime.
Basically get the classpath of your app and scan through the available classes and read the bytecode information of a class which class it inherits from. Note that a class Dog may not directly inherit from Animal but might inherit from Pet which is turn inherits from Animal,so you will need to keep track of that hierarchy.
One way is to make the classes use a static initializers... I don't think these are inherited (it won't work if they are):
public class Dog extends Animal{
static
{
Animal a = new Dog();
//add a to the List
}
It requires you to add this code to all of the classes involved. But it avoids having a big ugly loop somewhere, testing every class searching for children of Animal.
I solved this problem pretty elegantly using Package Level Annotations and then making that annotation have as an argument a list of classes.
Find Java classes implementing an interface
Implementations just have to create a package-info.java and put the magic annotation in with the list of classes they want to support.
Since directly using newInstance() is deprecated, you can do it this way using Reflections.
Reflections r = new Reflections("com.example.location.of.sub.classes")
Set<Class<? extends Animal>> classes = r.getSubTypesOf(Animal.class);
classes.forEach(c -> {
Animal a = c.getDeclaredConstructor().newInstance();
//a is your instance of Animal.
});

Automatic class instantiation [duplicate]

I want to do something like this:
List<Animal> animals = new ArrayList<Animal>();
for( Class c: list_of_all_classes_available_to_my_app() )
if (c is Animal)
animals.add( new c() );
So, I want to look at all of the classes in my application's universe, and when I find one that descends from Animal, I want to create a new object of that type and add it to the list. This allows me to add functionality without having to update a list of things. I can avoid the following:
List<Animal> animals = new ArrayList<Animal>();
animals.add( new Dog() );
animals.add( new Cat() );
animals.add( new Donkey() );
...
With the above approach, I can simply create a new class that extends Animal and it'll get picked up automatically.
UPDATE: 10/16/2008 9:00 a.m. Pacific Standard Time:
This question has generated a lot of great responses -- thank you. From the responses and my research, I've found that what I really want to do is just not possible under Java. There are approaches, such as ddimitrov's ServiceLoader mechanism that can work -- but they are very heavy for what I want, and I believe I simply move the problem from Java code to an external configuration file. Update 5/10/19 (11 years later!) There are now several libraries that can help with this according to #IvanNik's answer org.reflections looks good. Also ClassGraph from #Luke Hutchison's answer looks interesting. There are several more possibilities in the answers as well.
Another way to state what I want: a static function in my Animal class finds and instantiates all classes that inherit from Animal -- without any further configuration/coding. If I have to configure, I might as well just instantiate them in the Animal class anyway. I understand that because a Java program is just a loose federation of .class files that that's just the way it is.
Interestingly, it seems this is fairly trivial in C#.
I use org.reflections:
Reflections reflections = new Reflections("com.mycompany");
Set<Class<? extends MyInterface>> classes = reflections.getSubTypesOf(MyInterface.class);
Another example:
public static void main(String[] args) throws IllegalAccessException, InstantiationException {
Reflections reflections = new Reflections("java.util");
Set<Class<? extends List>> classes = reflections.getSubTypesOf(java.util.List.class);
for (Class<? extends List> aClass : classes) {
System.out.println(aClass.getName());
if(aClass == ArrayList.class) {
List list = aClass.newInstance();
list.add("test");
System.out.println(list.getClass().getName() + ": " + list.size());
}
}
}
The Java way to do what you want is to use the ServiceLoader mechanism.
Also many people roll their own by having a file in a well known classpath location (i.e. /META-INF/services/myplugin.properties) and then using ClassLoader.getResources() to enumerate all files with this name from all jars. This allows each jar to export its own providers and you can instantiate them by reflection using Class.forName()
Think about this from an aspect-oriented point of view; what you want to do, really, is know all the classes at runtime that HAVE extended the Animal class. (I think that's a slightly more accurate description of your problem than your title; otherwise, I don't think you have a runtime question.)
So what I think you want is to create a constructor of your base class (Animal) which adds to your static array (I prefer ArrayLists, myself, but to each their own) the type of the current Class which is being instantiated.
So, roughly;
public abstract class Animal
{
private static ArrayList<Class> instantiatedDerivedTypes;
public Animal() {
Class derivedClass = this.getClass();
if (!instantiatedDerivedClass.contains(derivedClass)) {
instantiatedDerivedClass.Add(derivedClass);
}
}
Of course, you'll need a static constructor on Animal to initialize instantiatedDerivedClass... I think this'll do what you probably want. Note that this is execution-path dependent; if you have a Dog class that derives from Animal that never gets invoked, you won't have it in your Animal Class list.
Unfortunately this isn't entirely possible as the ClassLoader won't tell you what classes are available. You can, however, get fairly close doing something like this:
for (String classpathEntry : System.getProperty("java.class.path").split(System.getProperty("path.separator"))) {
if (classpathEntry.endsWith(".jar")) {
File jar = new File(classpathEntry);
JarInputStream is = new JarInputStream(new FileInputStream(jar));
JarEntry entry;
while( (entry = is.getNextJarEntry()) != null) {
if(entry.getName().endsWith(".class")) {
// Class.forName(entry.getName()) and check
// for implementation of the interface
}
}
}
}
Edit: johnstok is correct (in the comments) that this only works for standalone Java applications, and won't work under an application server.
The most robust mechanism for listing all subclasses of a given class is currently ClassGraph, because it handles the widest possible array of classpath specification mechanisms, including the new JPMS module system. (I am the author.)
List<Class<Animal>> animals;
try (ScanResult scanResult = new ClassGraph().whitelistPackages("com.zoo.animals")
.enableClassInfo().scan()) {
animals = scanResult
.getSubclasses(Animal.class.getName())
.loadClasses(Animal.class);
}
You could use ResolverUtil (raw source) from the Stripes Framework
if you need something simple and quick without refactoring any existing code.
Here's a simple example not having loaded any of the classes:
package test;
import java.util.Set;
import net.sourceforge.stripes.util.ResolverUtil;
public class BaseClassTest {
public static void main(String[] args) throws Exception {
ResolverUtil<Animal> resolver = new ResolverUtil<Animal>();
resolver.findImplementations(Animal.class, "test");
Set<Class<? extends Animal>> classes = resolver.getClasses();
for (Class<? extends Animal> clazz : classes) {
System.out.println(clazz);
}
}
}
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
class Donkey extends Animal {}
This also works in an application server as well since that's where it was designed to work ;)
The code basically does the following:
iterate over all the resources in the package(s) you specify
keep only the resources ending in .class
Load those classes using ClassLoader#loadClass(String fullyQualifiedName)
Checks if Animal.class.isAssignableFrom(loadedClass);
Java dynamically loads classes, so your universe of classes would be only those that have already been loaded (and not yet unloaded). Perhaps you can do something with a custom class loader that could check the supertypes of each loaded class. I don't think there's an API to query the set of loaded classes.
use this
public static Set<Class> getExtendedClasses(Class superClass)
{
try
{
ResolverUtil resolver = new ResolverUtil();
resolver.findImplementations(superClass, superClass.getPackage().getName());
return resolver.getClasses();
}
catch(Exception e)
{Log.d("Log:", " Err: getExtendedClasses() ");}
return null;
}
getExtendedClasses(Animals.class);
Edit:
library for (ResolverUtil) : Stripes
Thanks all who answered this question.
It seems this is indeed a tough nut to crack. I ended up giving up and creating a static array and getter in my baseclass.
public abstract class Animal{
private static Animal[] animals= null;
public static Animal[] getAnimals(){
if (animals==null){
animals = new Animal[]{
new Dog(),
new Cat(),
new Lion()
};
}
return animals;
}
}
It seems that Java just isn't set up for self-discoverability the way C# is. I suppose the problem is that since a Java app is just a collection of .class files out in a directory / jar file somewhere, the runtime doesn't know about a class until it's referenced. At that time the loader loads it -- what I'm trying to do is discover it before I reference it which is not possible without going out to the file system and looking.
I always like code that can discover itself instead of me having to tell it about itself, but alas this works too.
Thanks again!
Using OpenPojo you can do the following:
String package = "com.mycompany";
List<Animal> animals = new ArrayList<Animal>();
for(PojoClass pojoClass : PojoClassFactory.enumerateClassesByExtendingType(package, Animal.class, null) {
animals.add((Animal) InstanceFactory.getInstance(pojoClass));
}
This is a tough problem and you will need to find out this information using static analysis, its not available easily at runtime.
Basically get the classpath of your app and scan through the available classes and read the bytecode information of a class which class it inherits from. Note that a class Dog may not directly inherit from Animal but might inherit from Pet which is turn inherits from Animal,so you will need to keep track of that hierarchy.
One way is to make the classes use a static initializers... I don't think these are inherited (it won't work if they are):
public class Dog extends Animal{
static
{
Animal a = new Dog();
//add a to the List
}
It requires you to add this code to all of the classes involved. But it avoids having a big ugly loop somewhere, testing every class searching for children of Animal.
I solved this problem pretty elegantly using Package Level Annotations and then making that annotation have as an argument a list of classes.
Find Java classes implementing an interface
Implementations just have to create a package-info.java and put the magic annotation in with the list of classes they want to support.
Since directly using newInstance() is deprecated, you can do it this way using Reflections.
Reflections r = new Reflections("com.example.location.of.sub.classes")
Set<Class<? extends Animal>> classes = r.getSubTypesOf(Animal.class);
classes.forEach(c -> {
Animal a = c.getDeclaredConstructor().newInstance();
//a is your instance of Animal.
});

Is it possible to get a class by qualifier annotation using reflection?

I have an interface with many possible implementations. The right implementation should be chosen at the runtime. And so Reflection sounds to be the solution.
I have annotated these classes by a qualifier that has as argument an enumeration.
So, is it possible to get at runtime using reflection the right implementatoin class by passing the right enumeration to the annotation?
But, reflection is not mandatory if there is another way..
First, here it is the enumeration :
public enum CATEGORY {
A,B,C;
}
Then, here it the interface :
public interface GenericI{
void method1(CATEGORY arg);
// some other methods
}
And now, here there are the annotated implementations :
#MyAnnotation(CATEGORY.A)
public class impl1 implements GenericI{
void method1(CATEGORY arg){
// some work here
}
}
#MyAnnotation(CATEGORY.B)
public class impl2 implements GenericI{
void method1(CATEGORY arg){
// some work here
}
}
Finally, the proxy that at a way, select dynamically the right implementation using annotation and enumeration (probably it shouldn't implement GenericI ??):
public class MyProxy implements GenericI {
// Here we must be able to select the right implementation
}
Reflexion is an answer, but you need to get all the classes from the classpath, and examinate it to find the implementation of your interface.
You can use this reflection library and get all the implementations like this (if your interface name is MyInterface):
Reflections reflections = new Reflections("your.base.package", new SubTypesScanner(), new TypeAnnotationsScanner());
Set<Class<T extends MyInterface>> classes = reflections.getSubTypesOf(MyInterface.class);
for (Class<T extends MyInterface> c : classes) {
check if c is the rigth implementation!.
}
If you don't want to use a external library, you can use the Java Reflection API, and scan all packages, somethis like (see this answers to use instrumentation):
Instrumentation inst = InstrumentHook.getInstrumentation();
for (Class<?> c: inst.getAllLoadedClasses()) {
if (MyInterface.class.isAssignableFrom(c)) {
check if c is the rigth implementation!.
}
}
The first option allow you to save the Reflections object as a xml, so the component scan is saved and it's done only one time.
To check if the clazz have a Qualifier you can use:
if (c.isAnnotationPresent(Qualifier.class)) {
bingo!.
}
or is a property of the annotation:
if (c.isAnnotationPresent(Qualifier.class)) {
Qualifier q = c.getAnnotation(Qualifier.class);
if (q.theRight()) {
bingo!
}
}
I recommend you to see if the FactoryProblem is applycable to your problem, choose always Factory instead of Reflection.
An example "proxy":
public class MyProxy implements GenericI {
Map<Category, GenericI> generics;
public MyProxy() {
Reflections reflections = new Reflections("your.base.package", new SubTypesScanner(), new TypeAnnotationsScanner());
Set<Class<T extends MyInterface>> classes = reflections.getSubTypesOf(MyInterface.class);
generics = new HashMap<Category, GenericI>();
for (Class<T extends MyInterface> c : classes) {
map.put(c.getAnnotation(MyAnnotation.class).value(), c.newInstance());
}
}
void method1(CATEGORY arg){
map.get(arg).method1(arg);
}
}
This is extremely heavy and overcomplicated, if you use this, please add extensive test, and make MyProxy a Singleton.
If you use a IOC framework:
#Component
public class MyProxy implements GenericI {
#Autoriwed // If spring
List<GenericI> generics;
#Inject #Any // If CDI
private Instance<GenericI> services;
Map<Category, GenericI> generics;
#PostConstruct
void makeMap() {
generics = new HashMap<>();
for (GenericI component : generics) {
generics.put(
component.getClass().getAnnotation(MyAnnotation.class).value(),
component);
}
}
void method1(CATEGORY arg){
map.get(arg).method1(arg);
}
}
I assume you don't know al possible subclasses.

.Net equivalent for Java typed Class<>?

I'm a .NET guy, so let me first assert my understanding of a few Java concepts - correct me if I'm wrong.
Java Generics support the concept of bounded wildcards:
class GenericClass< ? extends IInterface> { ... }
...which is similar to the .NET where restriction:
class GenericClass<T> where T: IInterface { ... }
Java's Class class describes a type, and is roughly equivalent to .NET Type class
So far, so good. But I can't find a close enough equivalence to the Java genericly typed Class<T> where T is a bounded wildcard. This basically imposes a restriction on the types that the Class represents.
Let me give an example in Java.
String custSortclassName = GetClassName(); //only known at runtime,
// e.g. it can come from a config file
Class<? extends IExternalSort> customClass
= Class.forName("MyExternalSort")
.asSubclass(IExternalSort.class); //this checks for correctness
IExternalSort impl = customClass.newInstance(); //look ma', no casting!
The closest I could get in .NET is something like this:
String custSortclassName = GetClassName(); //only known at runtime,
// e.g. it can come from a config file
Assembly assy = GetAssembly(); //unimportant
Type customClass = assy.GetType(custSortclassName);
if(!customClass.IsSubclassOf(typeof(IExternalSort))){
throw new InvalidOperationException(...);
}
IExternalSort impl = (IExternalSort)Activator.CreateInstance(customClass);
The Java version looks cleaner to me.
Is there a way to improve the .NET counterpart ?
Using extension methods & a custom wrapper class for System.Type, you can get pretty close to the Java syntax.
NOTE: Type.IsSubclassOf cannot be used to test if a type implements an interface - see the linked documentation on MSDN. One can use Type.IsAssignableFrom instead - see the code below.
using System;
class Type<T>
{
readonly Type type;
public Type(Type type)
{
// Check for the subtyping relation
if (!typeof(T).IsAssignableFrom(type))
throw new ArgumentException("The passed type must be a subtype of " + typeof(T).Name, "type");
this.type = type;
}
public Type UnderlyingType
{
get { return this.type; }
}
}
static class TypeExtensions
{
public static Type<T> AsSubclass<T>(this System.Type type)
{
return new Type<T>(type);
}
}
// This class can be expanded if needed
static class TypeWrapperExtensions
{
public static T CreateInstance<T>(this Type<T> type)
{
return (T)Activator.CreateInstance(type.UnderlyingType);
}
}
Further improvements using interface variance
(Should only be used in production code after the performance has been evaluated. Could be improved by using a (concurrent!) cache dictionary ConcurrentDictionary<System.Type, IType<object>)
Using Covariant type parameters, a feature introduced with C# 4.0, and an additional type interface IType<out T>, which Type<T> implements, one could make things like the following possible:
// IExternalSortExtended is a fictional interface derived from IExternalSort
IType<IExternalSortExtended> extendedSort = ...
IType<IExternalSort> externalSort = extendedSort; // No casting here, too.
One could even do:
using System;
interface IType<out T>
{
Type UnderlyingType { get; }
}
static class TypeExtensions
{
private class Type<T> : IType<T>
{
public Type UnderlyingType
{
get { return typeof(T); }
}
}
public static IType<T> AsSubclass<T>(this System.Type type)
{
return (IType<T>)Activator.CreateInstance(
typeof(Type<>).MakeGenericType(type)
);
}
}
static class TypeWrapperExtensions
{
public static T CreateInstance<T>(this IType<T> type)
{
return (T)Activator.CreateInstance(type.UnderlyingType);
}
}
So that one can (explicitly) cast between unrelated interfaces InterfaceA and InterfaceB like:
var x = typeof(ConcreteAB).AsSubclass<InterfaceA>();
var y = (IType<InterfaceB>)x;
but that kinda defeats the purpose of the exercise.
C# generics is declaration-site variance, the variance of a type parameter is fixed.
Java is use-site variance, so once we have a declaration List<E>, we can use it 3 ways
List<Number> // invariant, read/write
List<+Number> // covariant, read only
List<-NUmber> // contravariant, write only
There are pros and cons to both approaches. The use-site approach is apparently more powerful, though it gained the reputation as being too difficult to programmers. I think it is actually pretty easy to grasp
List<Integer> integers = ...;
List<+Number> numbers = integers; // covariant
Unfortunately, Java invented an absolutely hideous syntax,
List<? extends Number> // i.e. List<+Number>
once your code has several of these it becomes really ugly. You have to learn to get over it.
Now, in the declaration-site camp, how do we achieve 3 variances on the same class? By having more types - a ReadOnlyList<out E>, a WriteOnlyList<in E>, and a List<E> extending both. This is not too bad, and one might say it's a better design. But it may become ugly if there are more type parameters. And if the designer of a class did not anticipate it being used variantly, the users of the class have no way to use it variantly.
You can get a slightly prettier version using the "as" operator:
String custSortclassName = GetClassName();
Assembly assy = GetAssembly();
Type customClass = assy.GetType(custSortclassName);
IExternalSort impl = Activator.CreateInstance(customClass) as IExternalSort;
if(impl==null) throw new InvalidOperationException(...);
But here I'm creating the instance before checking its type, which may be an issue for you.
You can try writing an extension method like the following:
static class TypeExtension
{
public static I NewInstanceOf<I>(this Type t)
where I: class
{
I instance = Activator.CreateInstance(t) as I;
if (instance == null)
throw new InvalidOperationException();
return instance;
}
}
Which can then be used in the following manner:
String custSortclassName = GetClassName(); //only known at runtime,
// e.g. it can come from a config file
Assembly assy = GetAssembly();
Type customClass = assy.GetType(custSortclassName);
IExternalSort impl = customClass.NewInstanceOf<IExternalSort>();

Is there a way to refer to the current type with a type variable?

Suppose I'm trying to write a function to return an instance of the current type. Is there a way to make T refer to the exact subtype (so T should refer to B in class B)?
class A {
<T extends A> foo();
}
class B extends A {
#Override
T foo();
}
To build on StriplingWarrior's answer, I think the following pattern would be necessary (this is a recipe for a hierarchical fluent builder API).
SOLUTION
First, a base abstract class (or interface) that lays out the contract for returning the runtime type of an instance extending the class:
/**
* #param <SELF> The runtime type of the implementor.
*/
abstract class SelfTyped<SELF extends SelfTyped<SELF>> {
/**
* #return This instance.
*/
abstract SELF self();
}
All intermediate extending classes must be abstract and maintain the recursive type parameter SELF:
public abstract class MyBaseClass<SELF extends MyBaseClass<SELF>>
extends SelfTyped<SELF> {
MyBaseClass() { }
public SELF baseMethod() {
//logic
return self();
}
}
Further derived classes can follow in the same manner. But, none of these classes can be used directly as types of variables without resorting to rawtypes or wildcards (which defeats the purpose of the pattern). For example (if MyClass wasn't abstract):
//wrong: raw type warning
MyBaseClass mbc = new MyBaseClass().baseMethod();
//wrong: type argument is not within the bounds of SELF
MyBaseClass<MyBaseClass> mbc2 = new MyBaseClass<MyBaseClass>().baseMethod();
//wrong: no way to correctly declare the type, as its parameter is recursive!
MyBaseClass<MyBaseClass<MyBaseClass>> mbc3 =
new MyBaseClass<MyBaseClass<MyBaseClass>>().baseMethod();
This is the reason I refer to these classes as "intermediate", and it's why they should all be marked abstract. In order to close the loop and make use of the pattern, "leaf" classes are necessary, which resolve the inherited type parameter SELF with its own type and implement self(). They should also be marked final to avoid breaking the contract:
public final class MyLeafClass extends MyBaseClass<MyLeafClass> {
#Override
MyLeafClass self() {
return this;
}
public MyLeafClass leafMethod() {
//logic
return self(); //could also just return this
}
}
Such classes make the pattern usable:
MyLeafClass mlc = new MyLeafClass().baseMethod().leafMethod();
AnotherLeafClass alc = new AnotherLeafClass().baseMethod().anotherLeafMethod();
The value here being that method calls can be chained up and down the class hierarchy while keeping the same specific return type.
DISCLAIMER
The above is an implementation of the curiously recurring template pattern in Java. This pattern is not inherently safe and should be reserved for the inner workings of one's internal API only. The reason is that there is no guarantee the type parameter SELF in the above examples will actually be resolved to the correct runtime type. For example:
public final class EvilLeafClass extends MyBaseClass<AnotherLeafClass> {
#Override
AnotherLeafClass self() {
return getSomeOtherInstanceFromWhoKnowsWhere();
}
}
This example exposes two holes in the pattern:
EvilLeafClass can "lie" and substitute any other type extending MyBaseClass for SELF.
Independent of that, there's no guarantee self() will actually return this, which may or may not be an issue, depending on the use of state in the base logic.
For these reasons, this pattern has great potential to be misused or abused. To prevent that, allow none of the classes involved to be publicly extended - notice my use of the package-private constructor in MyBaseClass, which replaces the implicit public constructor:
MyBaseClass() { }
If possible, keep self() package-private too, so it doesn't add noise and confusion to the public API. Unfortunately this is only possible if SelfTyped is an abstract class, since interface methods are implicitly public.
As zhong.j.yu points out in the comments, the bound on SELF might simply be removed, since it ultimately fails to ensure the "self type":
abstract class SelfTyped<SELF> {
abstract SELF self();
}
Yu advises to rely only on the contract, and avoid any confusion or false sense of security that comes from the unintuitive recursive bound. Personally, I prefer to leave the bound since SELF extends SelfTyped<SELF> represents the closest possible expression of the self type in Java. But Yu's opinion definitely lines up with the precedent set by Comparable.
CONCLUSION
This is a worthy pattern that allows for fluent and expressive calls to your builder API. I've used it a handful of times in serious work, most notably to write a custom query builder framework, which allowed call sites like this:
List<Foo> foos = QueryBuilder.make(context, Foo.class)
.where()
.equals(DBPaths.from_Foo().to_FooParent().endAt_FooParentId(), parentId)
.or()
.lessThanOrEqual(DBPaths.from_Foo().endAt_StartDate(), now)
.isNull(DBPaths.from_Foo().endAt_PublishedDate())
.or()
.greaterThan(DBPaths.from_Foo().endAt_EndDate(), now)
.endOr()
.or()
.isNull(DBPaths.from_Foo().endAt_EndDate())
.endOr()
.endOr()
.or()
.lessThanOrEqual(DBPaths.from_Foo().endAt_EndDate(), now)
.isNull(DBPaths.from_Foo().endAt_ExpiredDate())
.endOr()
.endWhere()
.havingEvery()
.equals(DBPaths.from_Foo().to_FooChild().endAt_FooChildId(), childId)
.endHaving()
.orderBy(DBPaths.from_Foo().endAt_ExpiredDate(), true)
.limit(50)
.offset(5)
.getResults();
The key point being that QueryBuilder wasn't just a flat implementation, but the "leaf" extending from a complex hierarchy of builder classes. The same pattern was used for the helpers like Where, Having, Or, etc. all of which needed to share significant code.
However, you shouldn't lose sight of the fact that all this only amounts to syntactic sugar in the end. Some experienced programmers take a hard stance against the CRT pattern, or at least are skeptical of the its benefits weighed against the added complexity. Their concerns are legitimate.
Bottom-line, take a hard look at whether it's really necessary before implementing it - and if you do, don't make it publicly extendable.
You should be able to do this using the recursive generic definition style that Java uses for enums:
class A<T extends A<T>> {
T foo();
}
class B extends A<B> {
#Override
B foo();
}
I may not fully understood the question, but isn't it enough to just do this (notice casting to T):
private static class BodyBuilder<T extends BodyBuilder> {
private final int height;
private final String skinColor;
//default fields
private float bodyFat = 15;
private int weight = 60;
public BodyBuilder(int height, String color) {
this.height = height;
this.skinColor = color;
}
public T setBodyFat(float bodyFat) {
this.bodyFat = bodyFat;
return (T) this;
}
public T setWeight(int weight) {
this.weight = weight;
return (T) this;
}
public Body build() {
Body body = new Body();
body.height = height;
body.skinColor = skinColor;
body.bodyFat = bodyFat;
body.weight = weight;
return body;
}
}
then subclasses won't have to use overriding or covariance of types to make mother class methods return reference to them...
public class PersonBodyBuilder extends BodyBuilder<PersonBodyBuilder> {
public PersonBodyBuilder(int height, String color) {
super(height, color);
}
}
Just write:
class A {
A foo() { ... }
}
class B extends A {
#Override
B foo() { ... }
}
assuming you're using Java 1.5+ (covariant return types).
If you want something akin to Scala's
trait T {
def foo() : this.type
}
then no, this is not possible in Java. You should also note that there is not much you can return from a similarly typed function in Scala, apart from this.
I found a way do this, it's sort of silly but it works:
In the top level class (A):
protected final <T> T a(T type) {
return type
}
Assuming C extends B and B extends A.
Invoking:
C c = new C();
//Any order is fine and you have compile time safety and IDE assistance.
c.setA("a").a(c).setB("b").a(c).setC("c");

Categories