0

First, this is similar to this question but there was never a satisfactory answer. Second: I know, I know, reflection is bad, but it is the only option I have.

Question: Given a class

package a.pkg.outside.my.code;

class ClassIWant {   // Package private class
    public ClassIWant instance() {...}
}

I want to call instance(), obtaining an instance of ClassIWant, and return a ClassIWant (not an Object).

I can successfully call instance via reflection and get my hands on an Object:

public class MyClass {
    /* type var T will always take value ClassIWant. I can currently get
     * get this to type check by using Class.cast and changing return
     * type to T, but this doesn't solve my problem.
     */
    public <T> ClassIWant callInstance() {  // Here T is ClassIWant
        Class<T> clazz = Class.forName("a.pkg.outside.my.code.ClassIWant");
        Object result = _use reflection_;
        return (ClassIWant) result;         // Fails at runtime
    }
}

The issue is that I don't have access to ClassIWant to cast, and the best I've been able to do is call clazz.cast(result). This returns type T, which doesn't quite do what I want.

It's not even clear to me that this is possible, but my program has been type checking and getting illegal access errors at runtime. This tells me that all the bits and pieces fit together on the type level, and that methods are all pointing to the right place.

Note: It may be possible to change my use case to not need an explicit ClassIWant, but this would probably be a fair amount of work (i.e., lots and lots of calls to reflection). For brevity I haven't included the use case---I'll treat this as a second question if need be.

Edit: Updated in response to Andy Turner's comment (thanks for the catch): in more detail, I'm not explicitly using T here, but I have access to it and I want to make that explicit

Ben Kushigian
  • 285
  • 1
  • 10
  • Maybe have a look at this post: https://stackoverflow.com/questions/15015675/accessing-non-visible-classes-with-reflection – Madjosz Jul 06 '19 at 19:40
  • `public ClassIWant callInstance()` isn't a valid method signature: type variables come before the return type. But then, you don't use the type variable. Please clarify. – Andy Turner Jul 06 '19 at 19:45
  • If you don't have access to the type, what are the API users going to do when being returned that type? Seems as if you'd have to replace the type on the class path with a public version to make this truly possible without fighting with the code. – Vince Jul 06 '19 at 19:49
  • @VinceEmigh I'm not completely sure how this all works together. From what I can tell, calling a method that expects a `ClassIWant` is fine, but explicitly casting to `ClassIWant` doesn't work. I guess I can try to write up some code to confirm that. – Ben Kushigian Jul 06 '19 at 19:54
  • It won't give a compiler error when calling `callInstance`, but the type information will be hidden, so API users won't be able to do anything with it (call methods and such, create reference variables for it allowing it to be passed around). So what would API users be able to do with it? – Vince Jul 06 '19 at 19:58
  • There is another method that does what I want---I am just trying to get the singleton instance that already exists (creating it if necessary), and pass this along to the method that already exists. – Ben Kushigian Jul 06 '19 at 20:02

0 Answers0