What is the use of anonymous classes in Java? Can we say that usage of anonymous class is one of the advantages of Java?
By an "anonymous class", I take it you mean anonymous inner class.
An anonymous inner class can come useful when making an instance of an object with certain "extras" such as overriding methods, without having to actually subclass a class.
I tend to use it as a shortcut for attaching an event listener:
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// do something
}
});
Using this method makes coding a little bit quicker, as I don't need to make an extra class that implements ActionListener -- I can just instantiate an anonymous inner class without actually making a separate class.
I only use this technique for "quick and dirty" tasks where making an entire class feels unnecessary. Having multiple anonymous inner classes that do exactly the same thing should be refactored to an actual class, be it an inner class or a separate class.
Anonymous inner classes are effectively closures, so they can be used to emulate lambda expressions or "delegates". For example, take this interface:
public interface F<A, B> {
B f(A a);
}
You can use this anonymously to create a first-class function in Java. Let's say you have the following method that returns the first number larger than i in the given list, or i if no number is larger:
public static int larger(final List<Integer> ns, final int i) {
for (Integer n : ns)
if (n > i)
return n;
return i;
}
And then you have another method that returns the first number smaller than i in the given list, or i if no number is smaller:
public static int smaller(final List<Integer> ns, final int i) {
for (Integer n : ns)
if (n < i)
return n;
return i;
}
These methods are almost identical. Using the first-class function type F, we can rewrite these into one method as follows:
public static <T> T firstMatch(final List<T> ts, final F<T, Boolean> f, T z) {
for (T t : ts)
if (f.f(t))
return t;
return z;
}
You can use an anonymous class to use the firstMatch method:
F<Integer, Boolean> greaterThanTen = new F<Integer, Boolean> {
Boolean f(final Integer n) {
return n > 10;
}
};
int moreThanMyFingersCanCount = firstMatch(xs, greaterThanTen, x);
This is a really contrived example, but its easy to see that being able to pass functions around as if they were values is a pretty useful feature. See "Can Your Programming Language Do This" by Joel himself.
A nice library for programming Java in this style: Functional Java.
Anonymous inner class is used in following scenario:
1.) For Overriding(subclassing), when class definition is not usable except current case:
class A{
public void methodA() {
System.out.println("methodA");
}
}
class B{
A a = new A() {
public void methodA() {
System.out.println("anonymous methodA");
}
};
}
2.) For implementing an interface, when implementation of interface is required only for current case:
interface InterfaceA{
public void methodA();
}
class B{
InterfaceA a = new InterfaceA() {
public void methodA() {
System.out.println("anonymous methodA implementer");
}
};
}
3.) Argument Defined Anonymous inner class:
interface Foo {
void methodFoo();
}
class B{
void do(Foo f) { }
}
class A{
void methodA() {
B b = new B();
b.do(new Foo() {
public void methodFoo() {
System.out.println("methodFoo");
}
});
}
}
I use them sometimes as a syntax hack for Map instantiation:
Map map = new HashMap() {{
put("key", "value");
}};
vs
Map map = new HashMap();
map.put("key", "value");
It saves some redundancy when doing a lot of put statements. However, I have also run into problems doing this when the outer class needs to be serialized via remoting.
They're commonly used as a verbose form of callback.
I suppose you could say they're an advantage compared to not having them, and having to create a named class every time, but similar concepts are implemented much better in other languages (as closures or blocks)
Here's a swing example
myButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
// do stuff here...
}
});
Although it's still messily verbose, it's a lot better than forcing you to define a named class for every throw away listener like this (although depending on the situation and reuse, that may still be the better approach)
You use it in situations where you need to create a class for a specific purpose inside another function, e.g., as a listener, as a runnable (to spawn a thread), etc.
The idea is that you call them from inside the code of a function so you never refer to them elsewhere, so you don't need to name them. The compiler just enumerates them.
They are essentially syntactic sugar, and should generally be moved elsewhere as they grow bigger.
I'm not sure if it is one of the advantages of Java, though if you do use them (and we all frequently use them, unfortunately), then you could argue that they are one.
GuideLines for Anonymous Class.
Anonymous class is declared and initialized simultaneously.
Anonymous class must extend or implement to one and only one class or interface resp.
As anonymouse class has no name, it can be used only once.
eg:
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
});
Yes, anonymous inner classes is definitely one of the advantages of Java.
With an anonymous inner class you have access to final and member variables of the surrounding class, and that comes in handy in listeners etc.
But a major advantage is that the inner class code, which is (at least should be) tightly coupled to the surrounding class/method/block, has a specific context (the surrounding class, method, and block).
new Thread() {
public void run() {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
System.out.println("Exception message: " + e.getMessage());
System.out.println("Exception cause: " + e.getCause());
}
}
}.start();
This is also one of the example for anonymous inner type using thread
An inner class is associated with an instance of the outer class and there are two special kinds: Local class and Anonymous class. An anonymous class enables us to declare and instantiate a class at same time, hence makes the code concise. We use them when we need a local class only once as they don't have a name.
Consider the example from doc where we have a Person class:
public class Person {
public enum Sex {
MALE, FEMALE
}
String name;
LocalDate birthday;
Sex gender;
String emailAddress;
public int getAge() {
// ...
}
public void printPerson() {
// ...
}
}
and we have a method to print members that match search criteria as:
public static void printPersons(
List<Person> roster, CheckPerson tester) {
for (Person p : roster) {
if (tester.test(p)) {
p.printPerson();
}
}
}
where CheckPerson is an interface like:
interface CheckPerson {
boolean test(Person p);
}
Now we can make use of anonymous class which implements this interface to specify search criteria as:
printPersons(
roster,
new CheckPerson() {
public boolean test(Person p) {
return p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25;
}
}
);
Here the interface is very simple and the syntax of anonymous class seems unwieldy and unclear.
Java 8 has introduced a term Functional Interface which is an interface with only one abstract method, hence we can say CheckPerson is a functional interface. We can make use of Lambda Expression which allows us to pass the function as method argument as:
printPersons(
roster,
(Person p) -> p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
);
We can use a standard functional interface Predicate in place of the interface CheckPerson, which will further reduce the amount of code required.
i use anonymous objects for calling new Threads..
new Thread(new Runnable() {
public void run() {
// you code
}
}).start();
Anonymous inner class can be beneficial while giving different implementations for different objects. But should be used very sparingly as it creates problem for program readability.
One of the major usage of anonymous classes in class-finalization which called finalizer guardian. In Java world using the finalize methods should be avoided until you really need them. You have to remember, when you override the finalize method for sub-classes, you should always invoke super.finalize() as well, because the finalize method of super class won't invoke automatically and you can have trouble with memory leaks.
so considering the fact mentioned above, you can just use the anonymous classes like:
public class HeavyClass{
private final Object finalizerGuardian = new Object() {
#Override
protected void finalize() throws Throwable{
//Finalize outer HeavyClass object
}
};
}
Using this technique you relieved yourself and your other developers to call super.finalize() on each sub-class of the HeavyClass which needs finalize method.
You can use anonymous class this way
TreeSet treeSetObj = new TreeSet(new Comparator()
{
public int compare(String i1,String i2)
{
return i2.compareTo(i1);
}
});
Seems nobody mentioned here but you can also use anonymous class to hold generic type argument (which normally lost due to type erasure):
public abstract class TypeHolder<T> {
private final Type type;
public TypeReference() {
// you may do do additional sanity checks here
final Type superClass = getClass().getGenericSuperclass();
this.type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
}
public final Type getType() {
return this.type;
}
}
If you'll instantiate this class in anonymous way
TypeHolder<List<String>, Map<Ineger, Long>> holder =
new TypeHolder<List<String>, Map<Ineger, Long>>() {};
then such holder instance will contain non-erasured definition of passed type.
Usage
This is very handy for building validators/deserializators. Also you can instantiate generic type with reflection (so if you ever wanted to do new T() in parametrized type - you are welcome!).
Drawbacks/Limitations
You should pass generic parameter explicitly. Failing to do so will lead to type parameter loss
Each instantiation will cost you additional class to be generated by compiler which leads to classpath pollution/jar bloating
An Anonymous Inner Class is used to create an object that will never be referenced again. It has no name and is declared and created in the same statement.
This is used where you would normally use an object's variable. You replace the variable with the new keyword, a call to a constructor and the class definition inside { and }.
When writing a Threaded Program in Java, it would usually look like this
ThreadClass task = new ThreadClass();
Thread runner = new Thread(task);
runner.start();
The ThreadClass used here would be user defined. This class will implement the Runnable interface which is required for creating threads. In the ThreadClass the run() method (only method in Runnable) needs to be implemented as well.
It is clear that getting rid of ThreadClass would be more efficient and that's exactly why Anonymous Inner Classes exist.
Look at the following code
Thread runner = new Thread(new Runnable() {
public void run() {
//Thread does it's work here
}
});
runner.start();
This code replaces the reference made to task in the top most example. Rather than having a separate class, the Anonymous Inner Class inside the Thread() constructor returns an unnamed object that implements the Runnable interface and overrides the run() method. The method run() would include statements inside that do the work required by the thread.
Answering the question on whether Anonymous Inner Classes is one of the advantages of Java, I would have to say that I'm not quite sure as I am not familiar with many programming languages at the moment. But what I can say is it is definitely a quicker and easier method of coding.
References: Sams Teach Yourself Java in 21 Days Seventh Edition
The best way to optimize code. also, We can use for an overriding method of a class or interface.
import java.util.Scanner;
abstract class AnonymousInner {
abstract void sum();
}
class AnonymousInnerMain {
public static void main(String []k){
Scanner sn = new Scanner(System.in);
System.out.println("Enter two vlaues");
int a= Integer.parseInt(sn.nextLine());
int b= Integer.parseInt(sn.nextLine());
AnonymousInner ac = new AnonymousInner(){
void sum(){
int c= a+b;
System.out.println("Sum of two number is: "+c);
}
};
ac.sum();
}
}
One more advantage:
As you know that Java doesn't support multiple inheritance, so if you use "Thread" kinda class as anonymous class then the class still has one space left for any other class to extend.
Related
New to RxJava and I have question about interface callbacks ( called from inner layer/module of code through interface variable) vs RxJava.
To make it more clear, quick example:
Standard callback interface implementation, interface, class A and B
interface CustomCallback {
void onCallbackCalled(String str);
}
class ClassA {
private ClassB classB;
public ClassA() {
classB = new ClassB(new CustomCallback() {
#Override
public void onCallbackCalled(String str) {
System.out.println("Callback called " + str);
}
});
}
}
class ClassB {
private CustomCallback customCallback;
public ClassB(CustomCallback callback) {
customCallback = callback;
}
private void somethingHappened() {
customCallback.onCallbackCalled("method somethingHappened");
}
}
When classB method "somethingHappened" is called, result is: "Callback called method somethingHappened".
Interface's method onCallbackCalled(String str) can be called from classB as many times as I want.
CLASS A ↓ ............................................ injection of interface through constructor
CLASS B................↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ onCallbackCalled(...) 0...n number
Now RxJava. 99% of cases which I find.
class ClassA {
private ClassB classB;
public ClassA() {
classB = new ClassB();
}
public void rxJavaMethod() {
DisposableObserver<String> observer = classB.getObservable()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableObserver<String>() {
#Override
public void onNext(String s) {}
#Override
public void onError(Throwable e) {}
#Override
public void onComplete() {}
});
}
}
class ClassB {
private Observable<String> getObservable() {
return Observable.just(can be different from "just", for sake of example);
}
}
Scheme is:
CLASS A ↓........................ one call for getting Observable resource
CLASS B................↑ EDIT returns observable which emits 0...n values
So basically you call from top layer ( in this example) and you get response about state from inner layer.
QUESTIONS:
1) What in case when you have a model ( inner layer) which is changing dynamically ( but not any kind of AsyncTask etc.), and you want to notify top layer ( UI for example) that state has changed ( good example: game).
2) Is there any kind of "bridge" class in RxJava library ( I think about it as "subscribe to it, then you can pass arguments to it as many times as you want and information/observable will be emitted to subscribers).
3) Is there any sense and advanatage of trying to do that instead of standard interface callbacks ( in case like above, not " click button, get response once")
UPDATE, ANSWER BASED ON EXAMPLE ABOVE
As Bob Dalgleish mentioned, way of making such bridge is by using one of the class extending Subject<T> rxjava.
http://reactivex.io/documentation/subject.html
class ClassA {
private ClassB classB;
public ClassA() {
classB = new ClassB();
}
public void rxJavaMethod() {
DisposableObserver<String> observer = classB.getCallbackSubjectRx()
.subscribeWith(new DisposableObserver<String>() {
#Override
public void onNext(String s) {}
#Override
public void onError(Throwable e) {}
#Override
public void onComplete() {}
});
}
}
class ClassB {
private BehaviorSubject<String> mCallbackRx;
public ClassB() {
mCallbackRx = BehaviorSubject.create();
}
// method somethingHappened can be invoked whenever whe want and
// it will send given parameter to all subscribers
private void somethingHappened() {
mCallbackRx.onNext("method somethingHappened");
}
// multiple subscribers allowed
public BehaviorSubject<String> getCallbackSubjectRx() {
return mCallbackRx;
}
}
Downside might be, that if we want to use one "bridge" to handle multiple callback types ( interface have methods, we use only one method: "onNext()"), we might need to create wrapper class with callback parameters. Which isn't big problem in my opinion.
On the other hand, we get access to all of RxJava operators.
http://reactivex.io/documentation/operators.html
( Example above is for RxJava2, where Disposable is basically Subscription from RxJava1).
The first thing to note is that
CLASS B................↑ returns 0...n observables to observer
is not true. Class B returns an observable, on which it will occasionally emit 0..n values.
(the question is not clear). The inner observable, from class B, is changing state for whatever reason. The most common reason is that another process/task/thread is feeding it, and you want to display the resulting state in the UI.
A simple type of "bridging" class that I use all the time any of the several Subject<> classes. You can emit new values to them using .onNext() and the subscribers will get those values.
If callback interfaces were all standardized, then they would have some advantage, but they vary all over the place. You have to remember that you need some particular interface for this thing you are looking at and and a different one for the other thing. While UI events tend to be quite uniform these days, trying to mix UI events and network events and database events will still leave you feeling overwhelmed. Having a much smaller class of interfaces, mostly encapsulated inside of the rxJava generic classes, makes composing functionality much easier.
Edit: Improve example code.
There is a good article from Yammer Engineering on using Observable.create() (formerly Observable.fromEmitter(), formerly Observable.fromAsync(). The important points he makes are
Using Observable.create() handles the subscription step for you by registering a listener to the underlying interface. More importantly, it arranges to de-register the listener when the unsubscribe() occurs.
Out of the box, this code handles multiple subscribers, each of which receives its own observable stream of data.
As I mentioned above, the listener protocol is particular to the thing you register with. If that thing supports only a single listener, then you will likely want to introduce a Subject that subscribes to the thing under observation, and all your other observers subscribe to the subject.
End of edit.
My favorite example of composition of solutions is the distinctUntilChanged() operator. Because it is an operator that works on a generic observable, it encapsulates the stateful property of saving consecutive values for comparison and only emitting differing ones. I use it frequently for logging state changes. To achieve the same end using standard callback interfaces would require adding a different interface for saving prior values to every existing interface.
So, yes, most of the time it is worth using the rxJava approach of observables, simply for the sake of not having to remember which of the many call back protocols might be applicable in the current case.
I have seen that constructors aren't allowed within an interface, however how is this allowed?:
locationListener = new LocationListener() {
etc }
Yes you are right interfaces can't have constructors but what you described is Anonymous Class. In this line you are creating object of new class without name that extends LocationListener (and implementation of it is between curly brackets).
If you want to get know some more about Anonymous Classes look here: https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html
This is Anonymous class approach. To make it clear, here is an example.
interface Animal {
public void cry();
}
To create an object of Animal instance, you need to implement the Animal interface first.
class Lion implements Animal {
public void cry() {
System.out.println("Roar");
}
}
Then create an object using the usual approach:
Animal theLion = new Lion();
Another way is to create an Animal object using the Anonymous class.
Animal theTiger = new Animal() {
public void cry() {
System.out.println("Grrr");
}
}
Now, both object should be able to call the cry method as:
theLion.cry();
theTiger.cry();
Cheers!
Here is my scenario.
I have an android activity in which I want to abstract my I/O dependencies. The dependencies are represented by this interface (edited for brevity and simplicity):
public interface ITimeDataServer {
TimeRecord[] get(int userID);
void save(TimeRecord record);
}
What I want is for my activity to be able to call these interface methods, and leave the implementation to be supplied by the calling code. (Pretty standard, I think).
ITimeDataServer myServer;
int myUserID;
void loadRecords() {
TimeRecord[] records = myServer.get(myUserID);
// etc...
}
My difficulty is, how can I ensure that myServer gets set?
This seems like a common problem, but I can't find a clean solution.
My first thought would be that myServer would be passed in through the constructor, but Android activities aren't really instantiated with constructors.
I've come up with several solutions, but they're all icky in some way:
Icky Solution 1
Create a static method to launch the activity class which takes an ITimeDataServer parameter and stores it in a static variable from which the activity can access it:
private static ITimeDataSource theDataSource;
public static void launch(Activity currentActivity, ITimeDataSource dataSource) {
theDataSource = dataSource;
Intent intent = new Intent(currentActivity, MainActivity.class);
currentActivity.startActivity(intent);
}
This is icky because (a) the data source is static and not actually associated with the instance, and (b) a consumer could initiate the activity by the standard activity API rather than this static method, which will cause NullPointerException.
Icky Solution 2
I can create a Provider class which provides a singleton instance of ITimeDataSource, which needs to be initialized by the calling library before use:
public class TimeDataSourceProvider {
private static ITimeDataSource myDataSource = null;
public void initialize(ITimeDataSource dataSource) {
myDataSource = dataSource;
}
public ITimeDataSource get() {
if (myDataSource == null)
throw new NullPointerException("TimeDataSourceProvider.initialize() must be called before .get() can be used.");
else
return myDataSource;
}
}
This seems a little less icky, but it's still a little icky because the activity's dependency is not obvious, and since there may be many paths to launch it, it's highly possible that some of them would forget to call TimeDataSourceProvider.initialize().
Icky solution 3
As a variation on #2, create a static IODependencyProvider class which must be initialized with ALL dependencies on app startup.
public class IODependencyProvider {
static ITimeDataSource myTimeData;
static IScheduleDataSource myScheduleData; // etc
public static void initialize(ITimeDataSource timeData, IScheduleDataSource scheduleData /* etc */) {
myTimeData = timeData;
myScheduleData = scheduleData;
//etc
}
public static ITimeDataSource getTimeData() {
if (myTimeData == null)
throw new NullPointerException("IODependencyProvider.initialize() must be called before the getX() methods can be used.");
else
return myTimeData;
}
// getScheduleData(), etc
}
This seems superior to #1 and #2 since a failure to initialize would be much harder to sneak by, but it also creates interdependencies among the data types that otherwise need not exist.
...and other icky variations on that theme.
The common themes that make these solutions crappy:
the need to use static fields to pass non-serializable information to an activity
the lack of ability to enforce initialization of those static fields (and subsequent haphazardness)
inability to clearly identify an activity's dependencies (due to reliance on statics)
What's a nooby Android developer to do?
As long as these dependencies implement Parcelable correctly, you should be able to add them to your intent, then unparcel them as ITimeDataServer and get the correct class.
I found a nice solution here, in the least-loved answer.
I define the library activity as abstract and with no default constructor, but a constructor that takes an interface, like so:
public abstract class TimeActivity extends AppCompatActivity {
private ITimeDataSource myTimeDataSource;
public TimeActivity(#NonNull ITimeDataSource dataSource) {
myTimeDataSource = dataSource;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_time);
// do stuff with myTimeDataSource!
}
}
Then, the calling code can create a concrete subclass with its chosen implementation that does have a parameterless constructor. No static members, easy-peasy!
This allows you to abstract and inject all sorts of crazy behaviours! Woooo!
(Note that the concrete subclass activity needs to be manually added to AndroidManifest.xml, like all activities, or the app will crash when it tries to launch.)
I have a Tool class with two static methods, doSomething(Object) and callDoSomething(). The names are intuitive in that callDoSomething delegates its call to doSomething(Object);
public class Tool
{
public static void doSomething( Object o )
{
}
public static void callDoSomething()
{
doSomething( new Object());
}
}
I have a Test class for Tool and I'd like to verify if doSomething(Object) was called (I want to do Argument Matching too in the future)
#RunWith( PowerMockRunner.class )
#PrepareForTest( { Tool.class } )
public class ToolTest
{
#Test
public void toolTest()
{
PowerMockito.mockStatic( Tool.class );
Tool.callDoSomething();// error!!
//Tool.doSomething();// this works! it gets verified!
PowerMockito.verifyStatic();
Tool.doSomething( Mockito.argThat( new MyArgMatcher() ) );
}
class MyArgMatcher extends ArgumentMatcher<Object>
{
#Override
public boolean matches( Object argument )
{
return true;
}
}
}
Verify picks up doSomething(Object) if it's called directly. I've commented this code out above. Verify does NOT pick up doSomething(Object) when using callDoSomething, (this is the code shown above). This is my error log when running the code above:
Wanted but not invoked tool.doSomething(null);
However, there were other interactions with this mock.
at org.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl.performIntercept(MockitoMethodInvocationControl.java:260)
at org.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl.invoke(MockitoMethodInvocationControl.java:192)
at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:105)
at org.powermock.core.MockGateway.methodCall(MockGateway.java:60)
at Tool.doSomething(Tool.java)
at ToolTest.toolTest(ToolTest.java:22)
... [truncated]
I'd like to avoid making any changes to the Tool class. My question is, how can I verify doSomething(Object) was called from callDoSomething(), as well as perform some argument matching on doSomething's param
It sounds like you want to use a static spy (partial mock). The section of the PowerMock documentation that talks about mocking static has a note in the second bullet that could be easily missed:
(use PowerMockito.spy(class) to mock a specific method)
Note, in your example you're not actually mocking the behavior, just verifying the method is called. There's a subtle but important difference. If you don't want doSomething(Object) to be called you'd need to do something like this:
#Test
public void toolTest() {
PowerMockito.spy(Tool.class); //This will call real methods by default.
//This will suppress the method call.
PowerMockito.doNothing().when(Tool.class);
Tool.doSomething(Mockito.argThat( new MyArgMatcher() ));
Tool.callDoSomething();
//The rest isn't needed since you're already mocking the behavior
//but you can still leave it in if you'd like.
PowerMockito.verifyStatic();
Tool.doSomething(Mockito.argThat( new MyArgMatcher() ));
}
If you still want the method to fire though, just remove the two lines for doNothing(). (I added a simple System.out.println("do something " + o); to my version of Tool.java as an additional verification of doNothing().)
You can do your validation with this:
public class Tool{
public static boolean isFromCallDoSomethingMethod= false;
public static void doSomething(Object o){
}
public static void callDoSomething() {
doSomething(new Object());
isFromCallDoSomethingMethod= true;
}
}
You can do the verification as:
if(Tool.isFromCallDoSomethingMethod){
//you called doSomething() from callDoSomething();
}
REMEMBER
Don't forget to do the validation if you call the doSomething() from another way that is not from callDoSomething(), you can do this by ussing Tool.isFromCallDoSomethingMethod = false
Is this what you want?
I have a library that I plan on using in dex form. I want to compile directly against this library, but not export it. Instead I want to drop it in my resources and use a class loader to actually instantiate it.
So here's my library:
public class Foo {
public doFoo(String message) {
}
public doFoo(int count, String message) {
}
}
Now I want to call doFoo(). A lot. More than it's probably reasonable to use reflection for. Right now it works with:
public class FooConsumer {
private final DexClassLoader fooLoader;
public FooConsumer(DexClassLoader fooLoader) {
this.fooLoader = fooLoader;
}
public void go() {
Class<?> fooClass = fooLoader.loadClass("com.library.Foo");
Object fooInstance = fooClass.newInstance();
Method fooMethodDoFoo = fooClass.getMethod("doFoo", String.class);
fooMethodDoFoo.invoke(fooInstance, "Hello World");
}
This is obviously fugly. Especially since I haven't included any of the exception handling, as there are half a dozen throwables to catch in there. I could cache a bunch of stuff, helping me with speed a bit, but not a lot.
Normally I'd have both aware of a third library that has an interface, but the library has some static methods and I can't edit it anyway. It'd be really nice if I could do something like:
public class FooConsumer {
private FooAccessor accessor;
public FooConsumer(DexClassLoader fooLoader) {
Object fooInstance = fooLoader.loadClass("com.library.Foo").newInstance();
Log.i("TEST", "fooInstance: " + fooInstance);
this.accessor = new FooAccessor(fooInstance);
}
public void go() {
accessor.doFoo("Hello World");
}
private static class FooAccessor {
private Foo fooInstance;
public FooAccessor(Object instance) {
fooInstance = (Foo)instance;
}
public void doFoo(String message) {
fooInstance.doFoo(message);
}
}
}
See what I did there? The inner class is just a wrapper around the Foo object, I've linked against it, but not exported it, and all is good in the world. But it doesn't work. In logcat I get
I/TEST: fooInstance: com.library.Foo#413b1b68
E/AndroidRuntime: java.lang.NoClassDefFoundError: com.library.Foo
...
Is there a way to have FooAccessor use the class loader I passed in? Or is the use of class loaders a damnation into reflection hell.
You might want to take a look at this gist.
https://gist.github.com/nickcaballero/7045993
It uses reflection to merge the new DexClassLoader to in-stock BaseDexClassLoader.