Since Java 8 interfaces could have default methods.
I know how to invoke the method explicitly from the implementing method, i.e.
(see Explicitly calling a default method in Java)
But how do I explicitly invoke the default method using reflection for example on a proxy?
Example:
interface ExampleMixin {
String getText();
default void printInfo(){
System.out.println(getText());
}
}
class Example {
public static void main(String... args) throws Exception {
Object target = new Object();
Map<String, BiFunction<Object, Object[], Object>> behavior = new HashMap<>();
ExampleMixin dynamic =
(ExampleMixin) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),new Class[]{ExampleMixin.class}, (Object proxy, Method method, Object[] arguments) -> {
//custom mixin behavior
if(behavior.containsKey(method.getName())) {
return behavior.get(method.getName()).apply(target, arguments);
//default mixin behavior
} else if (method.isDefault()) {
//this block throws java.lang.IllegalAccessException: no private access for invokespecial
return MethodHandles.lookup()
.in(method.getDeclaringClass())
.unreflectSpecial(method, method.getDeclaringClass())
.bindTo(target)
.invokeWithArguments();
//no mixin behavior
} else if (ExampleMixin.class == method.getDeclaringClass()) {
throw new UnsupportedOperationException(method.getName() + " is not supported");
//base class behavior
} else{
return method.invoke(target, arguments);
}
});
//define behavior for abstract method getText()
behavior.put("getText", (o, a) -> o.toString() + " myText");
System.out.println(dynamic.getClass());
System.out.println(dynamic.toString());
System.out.println(dynamic.getText());
//print info should by default implementation
dynamic.printInfo();
}
}
Edit: I know a similar question has been asked in How do I invoke Java 8 default methods refletively, but this has not solved my problem for two reasons:
the problem described in that question aimed on how to invoked it via reflection in general - so no distinction between default and overriden method was made - and this is simple, you only need an instance.
one of the answers - using method handles - does only work with nasty hack (imho) like changing access modifiers to fields of the lookup class, which is the same category of "solutions" like this: Change private static final field using Java reflection: it's good to know it's possible, but I wouldn't use it in production - I'm looking for an "official" way to do it.
The IllegalAccessException is thrown in unreflectSpecial
Caused by: java.lang.IllegalAccessException: no private access for invokespecial: interface example.ExampleMixin, from example.ExampleMixin/package
at java.lang.invoke.MemberName.makeAccessException(MemberName.java:852)
at java.lang.invoke.MethodHandles$Lookup.checkSpecialCaller(MethodHandles.java:1568)
at java.lang.invoke.MethodHandles$Lookup.unreflectSpecial(MethodHandles.java:1227)
at example.Example.lambda$main$0(Example.java:30)
at example.Example$$Lambda$1/1342443276.invoke(Unknown Source)
I've been troubled by similar issues as well when using MethodHandle.Lookup in JDK 8 - 10, which behave differently. I've blogged about the correct solution here in detail.
This approach works in Java 8
In Java 8, the ideal approach uses a hack that accesses a package-private constructor from Lookup:
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Constructor;
import java.lang.reflect.Proxy;
interface Duck {
default void quack() {
System.out.println("Quack");
}
}
public class ProxyDemo {
public static void main(String[] a) {
Duck duck = (Duck) Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class[] { Duck.class },
(proxy, method, args) -> {
Constructor<Lookup> constructor = Lookup.class
.getDeclaredConstructor(Class.class);
constructor.setAccessible(true);
constructor.newInstance(Duck.class)
.in(Duck.class)
.unreflectSpecial(method, Duck.class)
.bindTo(proxy)
.invokeWithArguments(args);
return null;
}
);
duck.quack();
}
}
This is the only approach that works with both private-accessible and private-inaccessible interfaces. However, the above approach does illegal reflective access to JDK internals, which will no longer work in a future JDK version, or if --illegal-access=deny is specified on the JVM.
This approach works on Java 9 and 10, but not 8
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Proxy;
interface Duck {
default void quack() {
System.out.println("Quack");
}
}
public class ProxyDemo {
public static void main(String[] a) {
Duck duck = (Duck) Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class[] { Duck.class },
(proxy, method, args) -> {
MethodHandles.lookup()
.findSpecial(
Duck.class,
"quack",
MethodType.methodType(void.class, new Class[0]),
Duck.class)
.bindTo(proxy)
.invokeWithArguments(args);
return null;
}
);
duck.quack();
}
}
Solution
Simply implement both of the above solutions and check if your code is running on JDK 8 or on a later JDK and you'll be fine. Until you're not :)
If you use a concrete impl class as lookupClass and caller for the invokeSpecial it should correctly invoke the default implementation of the interface (no hack for private access needed):
Example target = new Example();
...
Class targetClass = target.getClass();
return MethodHandles.lookup()
.in(targetClass)
.unreflectSpecial(method, targetClass)
.bindTo(target)
.invokeWithArguments();
This of course only works if you have a reference to a concrete object implementing the interface.
Edit: this solution will only work if the class in question (Example in the code above), is private accessible from the caller code, e.g. an anonymous inner class.
The current implementation of the MethodHandles/Lookup class will not allow to call invokeSpecial on any class that is not private accessible from the current caller class. There are various work-arounds available, but all of them require the use of reflection to make constructors/methods accessible, which will probably fail in case a SecurityManager is installed.
In Java 16 (from the documentation, which also has more complex examples):
Object proxy = Proxy.newProxyInstance(loader, new Class[] { A.class },
(o, m, params) -> {
if (m.isDefault()) {
// if it's a default method, invoke it
return InvocationHandler.invokeDefault(o, m, params);
}
});
}
If all you have is an interface, and all you have access to is a class object is an interface that extends your base interface, and you want to call the default method without a real instance of a class that implements the interface, you can:
Object target = Proxy.newProxyInstance(classLoader,
new Class[]{exampleInterface}, (Object p, Method m, Object[] a) -> null);
Create an instance of the interface, and then construct the MethodHandles.Lookup using reflection:
Constructor<MethodHandles.Lookup> lookupConstructor =
MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, Integer.TYPE);
if (!lookupConstructor.isAccessible()) {
lookupConstructor.setAccessible(true);
}
And then use that lookupConstructor to create a new instance of your interface that will allow private access to invokespecial. Then invoke the method on the fake proxy target you made earlier.
lookupConstructor.newInstance(exampleInterface,
MethodHandles.Lookup.PRIVATE)
.unreflectSpecial(method, declaringClass)
.bindTo(target)
.invokeWithArguments(args);
Use:
Object result = MethodHandles.lookup()
.in(method.getDeclaringClass())
.unreflectSpecial(method, method.getDeclaringClass())
.bindTo(target)
.invokeWithArguments();
We can see how spring process default method.
try invoke public method MethodHandles.privateLookupIn(Class,Lookup) first. This should success on jdk9+.
try create a Lookup with package private constructor MethodHandles.Lookup(Class).
fallback to MethodHandles.lookup().findSpecial(...)
https://github.com/spring-projects/spring-data-commons/blob/2.1.8.RELEASE/src/main/java/org/springframework/data/projection/DefaultMethodInvokingMethodInterceptor.java
T. Neidhart answer almost worked but I got the java.lang.IllegalAccessException: no private access for invokespecial
Changing to use MethodHandles.privateLookup() solved it
return MethodHandles.privateLookupIn(clazz,MethodHandles.lookup())
.in(clazz)
.unreflectSpecial(method, clazz)
.bindTo(proxy)
.invokeWithArguments(args);
Here's a full example, the idea is that a user that extends a provided IMap can access nested nested map's with he's custom interface
interface IMap {
Object get(String key);
default <T> T getAsAny(String key){
return (T)get(key);
}
default <T extends IMap> T getNestedAs(String key, Class<T> clazz) {
Map<String,Object> nested = getAsAny(key);
return (T)Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{clazz}, (proxy, method, args) -> {
if (method.getName().equals("get")){
return nested.get(args[0]);
}
return MethodHandles.privateLookupIn(clazz, MethodHandles.lookup())
.in(clazz)
.unreflectSpecial(method, clazz)
.bindTo(proxy)
.invokeWithArguments(args);
}
);
}
}
interface IMyMap extends IMap{
default Integer getAsInt(String key){
return getAsAny(key);
}
default IMyMap getNested(String key){
return getNestedAs(key,IMyMap.class);
}
}
#Test
public void test(){
var data =Map.of("strKey","strValue", "nstKey", Map.of("intKey",42));
IMyMap base = data::get;
IMyMap myMap = base.getNested("nstKey");
System.out.println( myMap.getAsInt("intKey"));
}
Lukas' answer works on Android 8+ (earlier releases do not have default methods) but relies on a private API that was blocked in later Android releases. Fortunately, the alternative constructor also works and is in grey list (unsupported) for now. The example (written in Kotlin) can be seen here.
#get:RequiresApi(26)
private val newLookup by lazy #TargetApi(26) {
MethodHandles.Lookup::class.java.getDeclaredConstructor(Class::class.java, Int::class.java).apply {
isAccessible = true
}
}
#RequiresApi(26)
fun InvocationHandler.invokeDefault(proxy: Any, method: Method, vararg args: Any?) =
newLookup.newInstance(method.declaringClass, 0xf) // ALL_MODES
.unreflectSpecial(method, method.declaringClass)
.bindTo(proxy)
.invokeWithArguments(*args)
Related
I have the following class:
class Processor<T> {
void process( T request ) {...}
}
I then call the following:
Processor<String> p = Processor.class.newInstance();
Eclipse complains, as a warning against Processor.class.newInstance():
"Type safety: The expression of type Processor needs unchecked
conversion to conform to Processor< String>"
How do I specify the template parameters to this expression? Something like:
Processor<String> p = Processor.class.newInstance<String>();
You have been answered about the reason for warning in the comments, by using Supplier instead, available in Java 8:
class Ideone {
public static void main(String[] args) {
ProcessorFactory<Processor<String>> pf =
new ProcessorFactory(Processor<String>::new);
Processor<String> p = pf.build();
p.process("Ciao!");
}
}
class Processor<T> {
void process( T request ) {
System.out.println(request);
}
}
class ProcessorFactory<T> {
private Supplier<T> supplier;
ProcessorFactory(Supplier<T> supplier) {
this.supplier = supplier;
}
T build() {
return supplier.get();
}
}
Basically you delegate the generation to en external factory workhorse, which get fed types thru the Supplier, Processor<String>::new is a reference to the constructor (parameterised).
It is a lot of work for such small benefit, and I am not sure I would do that.
demo here: https://ideone.com/GxQOxG
I'm given the class object of some unknown concrete implementation of Processor
Instead of trying to do
Processor<String> processor = ConcreteProcessor.class.newInstance(); //warning
You can simply use the class object you have:
Processor<String> processor = classOfConcreteProcessor.newInstance();
Depending on the 'bigger system' you mentioned, type information will either be available or not.
If type inference is not possible in your case, you will either
have to build around it e.g. using factories / supplier
trust in yourself and suppress the compiler warnings
The problem is to create a dynamic enhanced version of existing objects.
I cannot modify the object's Class. Instead I have to:
subclass it
wrap the existing object in the new Class
delegate all the original method calls to the wrapped object
implement all methods that are defined by another interface
The interface to add to existing objects is:
public interface EnhancedNode {
Node getNode();
void setNode(Node node);
Set getRules();
void setRules(Set rules);
Map getGroups();
void setGroups(Map groups);
}
With Byte Buddy I managed to subclass and to implement my interface. The problem is the delegation to the wrapped object. The only way to do this that I found is using reflection what is too slow (I have heavy load on the application and performance is critical).
So far my code is:
Class<? extends Node> proxyType = new ByteBuddy()
.subclass(node.getClass(), ConstructorStrategy.Default.IMITATE_SUPER_TYPE_PUBLIC)
.method(anyOf(finalNode.getClass().getMethods())).intercept(MethodDelegation.to(NodeInterceptor.class))
.defineField("node", Node.class, Visibility.PRIVATE)
.implement(EnhancedNode.class).intercept(FieldAccessor.ofBeanProperty())
.defineField("groups", Map.class, Visibility.PRIVATE)
.implement(EnhancedNode.class).intercept(FieldAccessor.ofBeanProperty())
.defineField("rules", Set.class, Visibility.PRIVATE)
.implement(EnhancedNode.class).intercept(FieldAccessor.ofBeanProperty())
.make()
.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
enhancedClass = (Class<N>) proxyType;
EnhancedNode enhancedNode = (EnhancedNode) enhancedClass.newInstance();
enhancedNode.setNode(node);
where Node is the object to subclass/wrap. The NodeInterceptor forwards the invoked methods to the getNode property.
Here the code of the NodeInterceptor:
public class NodeInterceptor {
#RuntimeType
public static Object intercept(#Origin Method method,
#This EnhancedNode proxy,
#AllArguments Object[] arguments)
throws Exception {
Node node = proxy.getNode();
Object res;
if (node != null) {
res = method.invoke(method.getDeclaringClass().cast(node), arguments);
} else {
res = null;
}
return res;
}
}
Everything is working but the intercept method is too slow, I'm planning to use ASM directly to add the implementation of every method of Node but I hope there is a simpler way using Byte Buddy.
You probably want to use a Pipe rather than the reflection API:
public class NodeInterceptor {
#RuntimeType
public static Object intercept(#Pipe Function<Node, Object> pipe,
#FieldValue("node") Node proxy) throws Exception {
return proxy != null
? pipe.apply(proxy);
: null;
}
}
In order to use a pipe, you first need to install it. If you have Java 8 available, you can use java.util.Function. Otherwise, simply define some type:
interface Function<T, S> { S apply(T t); }
yourself. The name of the type and the method are irrelevant. The install the type:
MethodDelegation.to(NodeInterceptor.class)
.appendParameterBinder(Pipe.Binder.install(Function.class));
Are you however sure that the reflection part is the critical point of your application's performance problems? Are you caching the generated classes correctly and is your cache working efficiently? The reflection API is faster than its reputation, especially since use Byte Buddy tends to imply monomorphic call sites.
Finally, some general feedback. You are calling
.implement(EnhancedNode.class).intercept(FieldAccessor.ofBeanProperty())
multiple times. This has no effect. Also, method.getDeclaringClass().cast(node) is not necessary. The reflection API does the cast for you.
Take, for example, immutability. How could I modify an object to indicate that it has been made immutable already and need not be wrapped again?
Let us assume we do not want to use reflection to scan for setters as that would be inefficient and insufficient.
Example:
// Deliberately chosing lowercase because it is a system attribute.
interface immutable {
// Nothing in here I can think of.
}
// immute - have I invented a new word?
// What can I do with the return type to indicate immutability?
public static <T> List<T> immute(List<T> list) {
// If it's not an immutable
if (!(list instanceof immutable)) {
// Make it so - how can I stamp it so?
return Collections.<T>unmodifiableList(list);
}
// It is immutable already.
return list;
}
Further playing with the idea produced this foul solution - it is horrible and almost any other trick would be better but I felt I should post. Please please find a better solution:
public class Test {
// Deliberately chosing lowercase because it is a system attribute.
interface immutable {
// Nothing in here I can think of.
}
// immute - have I invented a new word?
// What can I do with the return type to indicate immutability?
public static <T> List<T> immute(List<T> list) {
// If it's not an immutable
if (!(list instanceof immutable)) {
// Make it so - how can I stamp it so?
return Hacker.hack(Collections.<T>unmodifiableList(list),
List.class,
immutable.class);
}
// It is immutable already - code DOES get here.
return list;
}
public void test() {
System.out.println("Hello");
List<String> test = new ArrayList<>();
test.add("Test");
test("Test", test);
List<String> immutableTest = immute(test);
test("Immutable Test", immutableTest);
List<String> immutableImmutableTest = immute(immutableTest);
test("Immutable Immutable Test", immutableImmutableTest);
}
private void test(String name, Object o) {
System.out.println(name + ":" + o.getClass().getSimpleName() + "=" + o);
}
public static void main(String args[]) {
new Test().test();
}
}
class Hacker {
// Hack an object to seem to implement a new interface.
// New interface should be instanceof testable.
// Suggest the additional type is an empty interface.
public static <T> T hack(final Object hack,
final Class<T> baseType,
final Class additionalType) {
return (T) Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class[]{baseType, additionalType},
new InvocationHandler() {
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Always invoke the method in the hacked object.
return method.invoke(hack, args);
}
});
}
}
If the check will be done on the same location, you could use a set or map, where you put all your wrapped objects, and check them later on in almost constant time. To avoid memory leaks, you could wrap them using weak references .
If the introduction of AOP is a (rather heavyweight) option, you could solve your problem using inter type declarations via AspectJ. This way, you could just add a private member with the reference to the corresponding wrapped instance to the Collection interface, if I remember correctly something like this:
aspect Unmodifieable {
private Collection java.util.Collection.unmofifieableWrapper = null;
public Collection java.util.Collection.getUnmodifieable() {
if (unmofifieableWrapper == null) {
unmofifieableWrapper = somehowRetrieveUnmodifieableCollection(this);
}
return unmofifieableWrapper;
}
}
You can do this with naming conventions in your classes.
interface MyObject;
class MyMutableObject implements MyObject;
class MyImmutableObject implements MyObject;
In my current project, I do something similar. I have an interface that needs to have a setter, but one of the implementing classes is immutable. When you call its setter it throws an Exception (it's setter should never be called, but it's there just to be safe).
The "information" you're looking for is more for the programmer than the compiler, so you don't need a language implemented "stamp".
The Collections.unmodifiable* methods return subtypes of UnmodifiableCollection so you could check UnmodifiableCollection.class.isAssignableFrom(list) then test the concrete types.
Without using instrumentation, I think you're stuck checking types.
I would like to create an object of Generics Type in java. Please suggest how can I achieve the same.
Note: This may seem a trivial Generics Problem. But I bet.. it isn't. :)
suppose I have the class declaration as:
public class Abc<T> {
public T getInstanceOfT() {
// I want to create an instance of T and return the same.
}
}
public class Abc<T> {
public T getInstanceOfT(Class<T> aClass) {
return aClass.newInstance();
}
}
You'll have to add exception handling.
You have to pass the actual type at runtime, since it is not part of the byte code after compilation, so there is no way to know it without explicitly providing it.
In the code you posted, it's impossible to create an instance of T since you don't know what type that is:
public class Abc<T>
{
public T getInstanceOfT()
{
// There is no way to create an instance of T here
// since we don't know its type
}
}
Of course it is possible if you have a reference to Class<T> and T has a default constructor, just call newInstance() on the Class object.
If you subclass Abc<T> you can even work around the type erasure problem and won't have to pass any Class<T> references around:
import java.lang.reflect.ParameterizedType;
public class Abc<T>
{
T getInstanceOfT()
{
ParameterizedType superClass = (ParameterizedType) getClass().getGenericSuperclass();
Class<T> type = (Class<T>) superClass.getActualTypeArguments()[0];
try
{
return type.newInstance();
}
catch (Exception e)
{
// Oops, no default constructor
throw new RuntimeException(e);
}
}
public static void main(String[] args)
{
String instance = new SubClass().getInstanceOfT();
System.out.println(instance.getClass());
}
}
class SubClass
extends Abc<String>
{
}
What you wrote doesn't make any sense, generics in Java are meant to add the functionality of parametric polymorphism to objects.
What does it mean? It means that you want to keep some type variables of your classes undecided, to be able to use your classes with many different types.
But your type variable T is an attribute that is resolved at run-time, the Java compiler will compile your class proving type safety without trying to know what kind of object is T so it's impossible for it to let your use a type variable in a static method. The type is associated to a run-time instance of the object while public void static main(..) is associated to the class definition and at that scope T doesn't mean anything.
If you want to use a type variable inside a static method you have to declare the method as generic (this because, as explained type variables of a template class are related to its run-time instance), not the class:
class SandBox
{
public static <T> void myMethod()
{
T foobar;
}
}
this works, but of course not with main method since there's no way to call it in a generic way.
EDIT: The problem is that because of type erasure just one generic class is compiled and passed to JVM. Type checker just checks if code is safe, then since it proved it every kind of generic information is discarded.
To instantiate T you need to know the type of T, but it can be many types at the same time, so one solution with requires just the minimum amount of reflection is to use Class<T> to instantiate new objects:
public class SandBox<T>
{
Class<T> reference;
SandBox(Class<T> classRef)
{
reference = classRef;
}
public T getNewInstance()
{
try
{
return reference.newInstance();
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
public static void main(String[] args)
{
SandBox<String> t = new SandBox<String>(String.class);
System.out.println(t.getNewInstance().getClass().getName());
}
}
Of course this implies that the type you want to instantiate:
is not a primitive type
it has a default constructor
To operate with different kind of constructors you have to dig deeper into reflection.
You need to get the type information statically. Try this:
public class Abc<T> {
private Class<T> clazz;
public Abc(Class<T> clazz) {
this.clazz = clazz;
}
public T getInstanceOfT()
throws throws InstantiationException,
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException,
NoSuchMethodException,
SecurityException {
return clazz.getDeclaredConstructor().newInstance();
}
}
Use it as such:
Abc<String> abc = new Abc<String>(String.class);
abc.getInstanceOfT();
Depending on your needs, you may want to use Class<? extends T> instead.
The only way to get it to work is to use Reified Generics. And this is not supported in Java (yet? it was planned for Java 7, but has been postponed). In C# for example it is supported assuming that T has a default constructor. You can even get the runtime type by typeof(T) and get the constructors by Type.GetConstructor(). I don't do C# so the syntax may be invalid, but it roughly look like this:
public class Foo<T> where T:new() {
public void foo() {
T t = new T();
}
}
The best "workaround" for this in Java is to pass a Class<T> as method argument instead as several answers already pointed out.
First of all, you can't access the type parameter T in the static main method, only on non-static class members (in this case).
Second, you can't instantiate T because Java implements generics with Type Erasure. Almost all the generic information is erased at compile time.
Basically, you can't do this:
T member = new T();
Here's a nice tutorial on generics.
You don't seem to understand how Generics work.
You may want to look at http://java.sun.com/j2se/1.5.0/docs/guide/language/generics.html
Basically what you could do is something like
public class Abc<T>
{
T someGenericThing;
public Abc(){}
public T getSomeGenericThing()
{
return someGenericThing;
}
public static void main(String[] args)
{
// create an instance of "Abc of String"
Abc<String> stringAbc = new Abc<String>();
String test = stringAbc.getSomeGenericThing();
}
}
I was implementing the same using the following approach.
public class Abc<T>
{
T myvar;
public T getInstance(Class<T> clazz) throws InstantiationException, IllegalAccessException
{
return clazz.newInstance();
}
}
I was trying to find a better way to achieve the same.
Isn't it possible?
Type Erasure Workaround
Inspired by #martin's answer, I wrote a helper class that allows me to workaround the type erasure problem. Using this class (and a little ugly trick) I'm able to create a new instance out of a template type:
public abstract class C_TestClass<T > {
T createTemplateInstance() {
return C_GenericsHelper.createTemplateInstance( this, 0 );
}
public static void main( String[] args ) {
ArrayList<String > list =
new C_TestClass<ArrayList<String > >(){}.createTemplateInstance();
}
}
The ugly trick here is to make the class abstract so the user of the class is forced to subtype it. Here I'm subclassing it by appending {} after the call to the constructor. This defines a new anonymous class and creates an instance of it.
Once the generic class is subtyped with concrete template types, I'm able to retrieve the template types.
public class C_GenericsHelper {
/**
* #param object instance of a class that is a subclass of a generic class
* #param index index of the generic type that should be instantiated
* #return new instance of T (created by calling the default constructor)
* #throws RuntimeException if T has no accessible default constructor
*/
#SuppressWarnings( "unchecked" )
public static <T> T createTemplateInstance( Object object, int index ) {
ParameterizedType superClass =
(ParameterizedType )object.getClass().getGenericSuperclass();
Type type = superClass.getActualTypeArguments()[ index ];
Class<T > instanceType;
if( type instanceof ParameterizedType ) {
instanceType = (Class<T > )( (ParameterizedType )type ).getRawType();
}
else {
instanceType = (Class<T > )type;
}
try {
return instanceType.newInstance();
}
catch( Exception e ) {
throw new RuntimeException( e );
}
}
}
There are hacky ways around this when you really have to do it.
Here's an example of a transform method that I find very useful; and provides one way to determine the concrete class of a generic.
This method accepts a collection of objects as input, and returns an array where each element is the result of calling a field getter on each object in the input collection. For example, say you have a List<People> and you want a String[] containing everyone's last name.
The type of the field value returned by the getter is specified by the generic E, and I need to instantiate an array of type E[] to store the return value.
The method itself is a bit ugly, but the code you write that uses it can be so much cleaner.
Note that this technique only works when somewhere in the input arguments there is an object whose type matches the return type, and you can deterministically figure it out. If the concrete classes of your input parameters (or their sub-objects) can tell you nothing about the generics, then this technique won't work.
public <E> E[] array (Collection c) {
if (c == null) return null;
if (c.isEmpty()) return (E[]) EMPTY_OBJECT_ARRAY;
final List<E> collect = (List<E>) CollectionUtils.collect(c, this);
final Class<E> elementType = (Class<E>) ReflectionUtil.getterType(c.iterator().next(), field);
return collect.toArray((E[]) Array.newInstance(elementType, collect.size()));
}
Full code is here: https://github.com/cobbzilla/cobbzilla-utils/blob/master/src/main/java/org/cobbzilla/util/collection/FieldTransformer.java#L28
It looks like you are trying to create the class that serves as the entry point to your application as a generic, and that won't work... The JVM won't know what type it is supposed to be using when it's instantiated as you start the application.
However, if this were the more general case, then something like would be what you're looking for:
public MyGeneric<MyChoiceOfType> getMeAGenericObject(){
return new MyGeneric<MyChoiceOfType>();
}
or perhaps:
MyGeneric<String> objMyObject = new MyGeneric<String>();
Abc<String> abcInstance = new Abc<String> ();
..for example
Is any practical way to reference a method on a class in a type-safe manner? A basic example is if I wanted to create something like the following utility function:
public Result validateField(Object data, String fieldName,
ValidationOptions options) { ... }
In order to call it, I would have to do:
validateField(data, "phoneNumber", options);
Which forces me to either use a magic string, or declare a constant somewhere with that string.
I'm pretty sure there's no way to get around that with the stock Java language, but is there some kind of (production grade) pre-compiler or alternative compiler that may offer a work around? (similar to how AspectJ extends the Java language) It would be nice to do something like the following instead:
public Result validateField(Object data, Method method,
ValidationOptions options) { ... }
And call it with:
validateField(data, Person.phoneNumber.getter, options);
As others mention, there is no real way to do this... and I've not seen a precompiler that supports it. The syntax would be interesting, to say the least. Even in your example, it could only cover a small subset of the potential reflective possibilities that a user might want to do since it won't handle non-standard accessors or methods that take arguments, etc..
Even if it's impossible to check at compile time, if you want bad code to fail as soon as possible then one approach is to resolve referenced Method objects at class initialization time.
Imagine you have a utility method for looking up Method objects that maybe throws error or runtime exception:
public static Method lookupMethod( Class c, String name, Class... args ) {
// do the lookup or throw an unchecked exception of some kind with a really
// good error message
}
Then in your classes, have constants to preresolve the methods you will use:
public class MyClass {
private static final Method GET_PHONE_NUM = MyUtils.lookupMethod( PhoneNumber.class, "getPhoneNumber" );
....
public void someMethod() {
validateField(data, GET_PHONE_NUM, options);
}
}
At least then it will fail as soon as MyClass is loaded the first time.
I use reflection a lot, especially bean property reflection and I've just gotten used to late exceptions at runtime. But that style of bean code tends to error late for all kinds of other reasons, being very dynamic and all. For something in between, the above would help.
There isn't anything in the language yet - but part of the closures proposal for Java 7 includes method literals, I believe.
I don't have any suggestions beyond that, I'm afraid.
Check out https://proxetta.jodd.org/refs/methref. It uses the Jodd proxy library (Proxetta) to proxy your type. Not sure about its performance characteristics, but it does provide type safety.
An example: Suppose Str.class has method .boo(), and you want to get its name as the string "boo":
String methodName = Methref.of(Str.class).name(Str::boo);
There's more to the API than the example above: https://oblac.github.io/jodd-site/javadoc/jodd/methref/Methref.html
Is any practical way to reference a method on a class in a type-safe manner?
First of all, reflection is type-safe. It is just that it is dynamically typed, not statically typed.
So, assuming that you want a statically typed equivalent of reflection, the theoretical answer is that it is impossible. Consider this:
Method m;
if (arbitraryFunction(obj)) {
m = obj.getClass().getDeclaredMethod("foo", ...);
} else {
m = obj.getClass().getDeclaredMethod("bar", ...);
}
Can we do this so that that runtime type exceptions cannot happen? In general NO, since this would entail proving that arbitraryFunction(obj) terminates. (This is equivalent to the Halting Problem, which is proven to be unsolvable in general, and is intractable using state-of-the-art theorem proving technology ... AFAIK.)
And I think that this road-block would apply to any approach where you could inject arbitrary Java code into the logic that is used to reflectively select a method from an object's class.
To my mind, the only moderately practical approach at the moment would be to replace the reflective code with something that generates and compiles Java source code. If this process occurs before you "run" the application, you've satisfied the requirement for static type-safety.
I was more asking about reflection in which the result is always the same. I.E. Person.class.getMethod("getPhoneNumber", null) would always return the same method and it's entirely possible to resolve it at compile time.
What happens if after compiling the class containing this code, you change Person to remove the getPhoneNumber method?
The only way you can be sure that you can resolve getPhoneNumber reflectively is if you can somehow prevent Person from being changed. But you can't do that in Java. Runtime binding of classes is a fundamental part of the language.
(For record, if you did that for a method that you called non-reflectively, you would get an IncompatibleClassChangeError of some kind when the two classes were loaded ...)
It has been pointed out that in Java 8 and later you could declare your validator something like this:
public Result validateField(Object data,
SomeFunctionalInterface function,
ValidationOptions options) { ... }
where SomeFunctionalInterface corresponds to the (loosely speaking) common signature of the methods you are validating.
Then you can call it with a method reference; e.g.
validateField(data, SomeClass::someMethod, options)
This is approach is statically type-safe. You will get a compilation error if SomeClass doesn't have someMethod or if it doesn't conform to SomeFunctionalInterface.
But you can't use a string to denote the method name. Looking up a method by name would entail either reflection ... or something else that side-steps static (i.e. compile time / load time) type safety.
Java misses the syntax sugar to do something as nice as Person.phoneNumber.getter. But if Person is an interface, you could record the getter method using a dynamic proxy. You could record methods on non-final classes as well using CGLib, the same way Mockito does it.
MethodSelector<Person> selector = new MethodSelector<Person>(Person.class);
selector.select().getPhoneNumber();
validateField(data, selector.getMethod(), options);
Code for MethodSelector: https://gist.github.com/stijnvanbael/5965609
Inspired by mocking frameworks, we could dream up the following syntax:
validator.validateField(data, options).getPhoneNumber();
Result validationResult = validator.getResult();
The trick is the generic declaration:
class Validator {
public <T> T validateField(T data, options) {...}
}
Now the return type of the method is the same as your data object's type and you can use code completion (and static checking) to access all the methods, including the getter methods.
As a downside, the code isn't quite intuitive to read, since the call to the getter doesn't actually get anything, but instead instructs the validator to validate the field.
Another possible option would be to annotate the fields in your data class:
class FooData {
#Validate(new ValidationOptions(...))
private PhoneNumber phoneNumber;
}
And then just call:
FooData data;
validator.validate(data);
to validate all fields according to the annotated options.
The framework picklock lets you do the following:
class Data {
private PhoneNumber phoneNumber;
}
interface OpenData {
PhoneNumber getPhoneNumber(); //is mapped to the field phoneNumber
}
Object data = new Data();
PhoneNumber number = ObjectAccess
.unlock(data)
.features(OpenData.class)
.getPhoneNumber();
This works in a similar way setters and private methods. Of course, this is only a wrapper for reflection, but the exception does not occur at unlocking time not at call time. If you need it at build time, you could write a unit test with:
assertThat(Data.class, providesFeaturesOf(OpenData.class));
I found a way to get the Method instance using Lambdas. It works only on interface methods though currently.
It works using net.jodah:typetools which is a very lightweight library.
https://github.com/jhalterman/typetools
public final class MethodResolver {
private interface Invocable<I> {
void invokeWithParams(I instance, Class<?>[] parameterTypes) throws Throwable;
}
interface ZeroParameters<I, R> extends Invocable<I> {
R invoke(I instance) throws Throwable;
#Override
default void invokeWithParams(I instance, Class<?>[] parameterTypes) throws Throwable {
invoke(instance);
}
}
public static <I, R> Method toMethod0(ZeroParameters<I, R> call) {
return toMethod(ZeroParameters.class, call, 1);
}
interface OneParameters<I, P1, R> extends Invocable<I> {
R invoke(I instance, P1 p1) throws Throwable;
#Override
default void invokeWithParams(I instance, Class<?>[] parameterTypes) throws Throwable {
invoke(instance, param(parameterTypes[1]));
}
}
public static <I, P1, R> Method toMethod1(OneParameters<I, P1, R> call) {
return toMethod(OneParameters.class, call, 2);
}
interface TwoParameters<I, P1, P2, R> extends Invocable<I> {
R invoke(I instance, P1 p1, P2 p2) throws Throwable;
#Override
default void invokeWithParams(I instance, Class<?>[] parameterTypes) throws Throwable {
invoke(instance, param(parameterTypes[1]), param(parameterTypes[2]));
}
}
public static <I, P1, P2, R> Method toMethod2(TwoParameters<I, P1, P2, R> call) {
return toMethod(TwoParameters.class, call, 3);
}
private static final Map<Class<?>, Object> parameterMap = new HashMap<>();
static {
parameterMap.put(Boolean.class, false);
parameterMap.put(Byte.class, (byte) 0);
parameterMap.put(Short.class, (short) 0);
parameterMap.put(Integer.class, 0);
parameterMap.put(Long.class, (long) 0);
parameterMap.put(Float.class, (float) 0);
parameterMap.put(Double.class, (double) 0);
}
#SuppressWarnings("unchecked")
private static <T> T param(Class<?> type) {
return (T) parameterMap.get(type);
}
private static <I> Method toMethod(Class<?> callType, Invocable<I> call, int responseTypeIndex) {
Class<?>[] typeData = TypeResolver.resolveRawArguments(callType, call.getClass());
Class<?> instanceClass = typeData[0];
Class<?> responseType = responseTypeIndex != -1 ? typeData[responseTypeIndex] : Void.class;
AtomicReference<Method> ref = new AtomicReference<>();
I instance = createProxy(instanceClass, responseType, ref);
try {
call.invokeWithParams(instance, typeData);
} catch (final Throwable e) {
throw new IllegalStateException("Failed to call no-op proxy", e);
}
return ref.get();
}
#SuppressWarnings("unchecked")
private static <I> I createProxy(Class<?> instanceClass, Class<?> responseType,
AtomicReference<Method> ref) {
return (I) Proxy.newProxyInstance(MethodResolver.class.getClassLoader(),
new Class[] {instanceClass},
(proxy, method, args) -> {
ref.set(method);
return parameterMap.get(responseType);
});
}
}
Usage:
Method method = MethodResolver.toMethod2(SomeIFace::foobar);
System.out.println(method); // public abstract example.Result example.SomeIFace.foobar(java.lang.String,boolean)
Method get = MethodResolver.<Supplier, Object>toMethod0(Supplier::get);
System.out.println(get); // public abstract java.lang.Object java.util.function.Supplier.get()
Method accept = MethodResolver.<IntFunction, Integer, Object>toMethod1(IntFunction::apply);
System.out.println(accept); // public abstract java.lang.Object java.util.function.IntFunction.apply(int)
Method apply = MethodResolver.<BiFunction, Object, Object, Object>toMethod2(BiFunction::apply);
System.out.println(apply); // public abstract java.lang.Object java.util.function.BiFunction.apply(java.lang.Object,java.lang.Object)
Unfortunately you have to create a new interface and method based on the parameter count and whether the method returns void or not.
However, if you have a somewhat fixed/limited method signature/parameter types, then this becomes quite handy.