I need to create a class that extends an abstract class in runtime in Android.
What I really need is to generate something like this:
Class A extends AbstractClass{
A(){
super("A name that is saved on AbstractClass");
fieldFromAbstractClass =...
}
#Override
public void aMethodFromAbstractClass(){
//some code....
}
}
I want to generate this at runtime. Is this possible?
In "traditional" Java, you can create and compile classes at runtime, or use byte code generators such as ASM to augment or generate class files.
However, you need to keep in mind that Android is not a Java virtual machine. When you create an APK, class files are converted into specialized bytecode that is processed by Android's Dalvik virtual machine.
I'm not aware of Dalvik-specific runtime bytecode generators, so I don't believe that it is (currently) possible to do what you described.
EDIT
There is a library called Dexmaker, which might accomplish this. I discovered it from this related answer.
You can make A an anonymous inner class. However, you cannot provide a new constructor. For your example define fieldFromAbstractClass in AbstractClass and provide a getter and a setter.
AbstractClass a = new AbstractClass() {
#Override
public void aMethodFromAbstractClass() {
// ...
}
}
a.setFieldFromAbstractClass( someValue );
// do something with A
You can also reference variables from the containing block in the inner class if the are declared final. For more information I recommend to read some Java tutorial or book.
Related
I tried to make a reflection to my code but I came across a problem because I had to extend class with reflected class, it was something like this:
I have this classes reflected:
"some.package.a.SomeClass"
"some.package.b.SomeClass"
and now I need to extend another class with one of them
public MyClass extends SomeClass {
#Override
public Object...
is there any way that I can achieve this?
Using off-the-shelf Java, you cannot extend a class given to you only through reflection. There are third-party libraries that let you overcome this restriction (see this Q&A).
Extending a class requires defining a new class, and compiling it into bytecode. Reflection happens at run-time. It is inherently a read-only API, so you cannot emit new classes with it.
Implementing an interface gives you another option of using a Proxy, but you cannot specify your own base class.
Consider this base class:
public class Cat {
public void meow() {
// meowing
}
}
And for some reason, cats subclasses can't inherit from this Cat class, because they MUST inherit from another base class, and Java doesn't support multiple inheritance. Thus:
public class Cat1 extends BaseClass1 {
}
public class Cat2 extends BaseClass2 {
}
public class Cat3 extends BaseClass3 {
}
How can I dynamically augment instances of CatX classes to inherit that meow method from Cat class?
A pseudo code might be:
public cat1Instance = new Cat1();
Cat.augmentWithCatBehavior(cat1Instance);
Is there a way for me to achieve this?
Update: Composition is not what I want. For composition, I need to have an instance of Cat class in all of my Cat1 to CatN classes. I have to create a wrapper method in each class so that I can call that meow. It's a huge amount of boilerplate code. That's why I said augmenting dynamically.
No, the structure of a Java class is fixed at compile time, and can only be inspected (using reflection) but not dynamically changed at runtime.
It is possible though to generate whole classes dynamically at runtime. Although that significantly defeats the purpose of using a statically compiled language, such as Java.
The other answer would be to look into AOP, which is supported in Java in some frameworks (for example in Spring AOP). Here the idea is to identify "crosscutting" concerns, and have the framework add the corresponding code in certain ways. A typical example of that would be to "annotate" methods to do "logging", and then the AOP framework just adds the code required to do some standardised logging.
Use an interface of Cat class instead of class and make your method default. Only for Java 8 and higher versions.
interface Cat {
default void meow() {
// meowing
}
}
public class Cat1 extends BaseClass1 implements Cat {
#Override public void meow() {}
}
And you can call the method of your child class as below:
Cat cat= new Cat1();
cat.meow();
You can't do that but you have two options open to explore
Using interface, its always good to use inheritance to assign behaviour rather than using inheritance.
Second option is using functional programming to return Consumer instance from the method which can be changed based on some logical condition.
Note: Functional programming enabled us in returning functions/behaviour which can help us a lot.
You cannot add methods to a class at runtime. You have two possible solutions:
Use an interface to work around the need for multiple inheritance.
Use an instance field and composition instead of inheritance.
I am using ASM library in Java to extract information of a class from compiled .class file. Now I am not able to get information of abstract classes implemented at runtime.
Where does JVM store information of abstract classes instantiated at runtime? Like below example.
public MockAbstractClass testForAbstract(){
return new MockAbstractClass() {
#Override
void abstractMethod() {
mockMethod();
}
}; }
static abstract class MockAbstractClass{
abstract void abstractMethod(); }
Here object of MockAbstractClass is created at runtime in testForAbstract() Method, also class is implemented at runtime.
Lambdas are an example where classes are generated at runtime.
The only way to access dynamically generated class is to store them via Instrumentation. There is a component which is called for every class defined by any means. You then need to store a reference to the byte code for those classes. You could optimise this to not store classes there the byte code can be retrieved from the classloader.
NOTE: For lambdas you don't get the class name or class loader but you can read the byte code to get the class name.
It is possible in plain Java to override a method of a class
programmatically at runtime (or even create a new method)?
I want to be able to do this even if I don't know the classes at compile time.
What I mean exactly by overriding at runtime:
abstract class MyClass{
public void myMethod();
}
class Overrider extends MyClass{
#Override
public void myMethod(){}
}
class Injector{
public static void myMethod(){ // STATIC !!!
// do actual stuff
}
}
// some magic code goes here
Overrider altered = doMagic(
MyClass.class, Overrider.class, Injector.class);
Now, this invocation...
altered.myMethod();
...would call Injector.myMethod() instead of Overrider.myMethod().
Injector.myMethod() is static, because, after doing "magic"
it is invoked from different class instance (it's the Overrider),
(so we prevent it from accessing local fields).
You can use something like cglib for generating code on-the-fly
In java6 has been added the possibility to transform any already loaded class. Take a look at the changes in the java.lang.instrument package
For interfaces there is java.lang.reflect.Proxy.
For classes you'll either need a third-party library or write a fair bit of code. Generally dynamically creating classes in this way is to create mocks for testing.
There is also the instrumentation API that allows modification of classes. You can also modify classes with a custom class loader or just the class files on disk.
I wrote an article for java.net about how to transparently add logging statements to a class when it is loaded by the classloader using a java agent.
It uses the Javassist library to manipulate the byte code, including using the Javassist compiler to generate extra bytecode which is then inserted in the appropriate place, and then the resulting class is provided to the classloader.
A refined version is available with the slf4j project.
If I got it right, the main problem that concerns you is how to pass a static method delegate (like in C#), through the instance interface method.
You can check this article: A Java Programmer Looks at C# Delegates (archived), which shows you how to get a reference to your static method and invoke it. You can then create a wrapper class which accepts the static method name in its constructor, and implements your base class to invoke the static method from the instance method.
I'm trying to slightly extend an undocumented class in a third-party framework we're using. I decompiled the .class file with jd-gui and see an inner class defined like this:
private class DeactivateAction extends AbstractAction {
public DeactivateAction() {
super("Deactivate");
}
public void actionPerformed(ActionEvent paramActionEvent) {
if (MyContainingType.this.someBoolean) {
MyContainingType.access$102(MyContainingType.this, false);
MyContainingType.this.add(MyContainingType.this.interceptor);
}
}
}
I am not sure how to interpret the "access$102" line here. MyContainingType extends javax.swing.JLayeredPane. This doesn't compile for me, so how can I interpret this and convert it correctly in my extended class?
That is a synthetic accessor.
Even inner classes don't really have access to their enclosing class's private members. The compiler "synthesizes" default (package) access methods to allow inner classes to work with private fields of the enclosing class.
You should be able to look at the enclosing class to figure out what access$102 is doing.
The javap tool, with the -c option can be very useful too.
AFAIK jd-gui is still improving on inner classes. Until version 0.2.9 I wasn't able to decompile inner classes at all. Now it works much better and I'm really lokking forward to the next releases!
'access$102' looks like a placeholder for a static method to me. You should be able to find something in MyContainingType that has a similiar signature.