(Java) Creating methods for new object created via reflection? - java

I have abstract methods in a class that need to be implemented by a foreign class in a SEPARATE project that uses my project.
-- All classes instanceof A are initially generated using reflection --
So anyway, say Class A is abstract, and Class B (non-abstract) extends A
B has all the unimplemented methods in Class A because B is in my workspace so I know to add those methods.
C also extends A, but C only has a subset of the abstract methods in A. C, however, is not in my workspace.
Therefore, for each abstract method in C NOT in A, I need to find some way to add the method for A like so:
(For each method)
public <corresponding return type> <missingMethodName>() { return null; }
Is this possible?
P.S. Please assume that I either have to completely rewrite my code to be in sync with the objects I have no control over, or implement a solution like the one I am alluding to above.

No, unless I'm reading you incorrectly, what you're asking for doesn't really make much sense.
If you wanted to inject a method
public <corresponding return type> <missingMethodName>() { super.<missingMethodName>(); }
into C, which extends A, which doesn't implement that method, what would it exactly do?
If you want to provide a default implementation in A, that's fine, and it won't affect C. If you add abstract methods into A, C must implement them, mark itself as abstract, or it won't compile (or throw serialization, or some weird error) if you run with a C compiled with an older A.

You should never need to do this as any instance method which has a super implementation can be called on a sub-class instance.
You can add these methods using byte code, but the only difference they would make is to change the list of getDefinedMethods(). However it wouldn't change the behaviour of the objects of the class.

its quiet difficult but you can do it with Javassist
Javassist (Java programming assistant) is a Java library providing a means to manipulate the Java bytecode of an application.1 In this sense Javassist provides the support for structural reflection, i.e. the ability to change the implementation of a class at run time.
Bytecode manipulation is performed at load-time through a provided class loader.
http://en.wikipedia.org/wiki/Javassist

Related

SemVer: can new functionality be considered breaking change?

Consider a library that defines a class A, with several methods (A1, A2, ...), at version 1.0.0 (semantic versioning)
Now imagine I add a new method to A object (method Ab). Is this a minor release? Because it adds functionality, and it shouldn't be a breaking change.
But if someone who's using the library declared a class A that extends class B, and B defines a method Ab with the same signature than the new method, now the code won't compile because it required the override declaration (in Scala and Java).
So, is this a breaking change?
First of all, adding a public method to a class in general is not a breaking change in semantic versioning. Removing a public method however would be a clear breaking change.
If you provide a Java library and you add a method to an interface, this is a breaking change, since others have to change / extend their code.
If you add a public method to a class, this will only be a problem, if this class is not final, so other can extend it and override methods.
So the best way I think is to declare a class as final, so the problem with method override should never happen. You can also leave the major update and only increase the minor one. Adding methods to interfaces will be a breaking change, so there you should increase the major version.

Work-around for assigning to this in Java?

After reading this thread, I understand that it is not possible to assign to this in Java. But are there any workarounds? I have the following situation. I'm writing a subclass B, but the base class A does not have any explicit constructors or methods that would allow to create the object given my arguments. The only available way is to call some external function F():
public class B extends A {
public B(some args) {
A a = F(some args);
this = a;
}
}
Both A and F() are from external libraries, A is a pretty complex object, and F() implements a sophisticated algorithm.
The only solution I can think of, is simply not to make a subclass:
public class B {
public A a;
public B(some args) {
a = F(some args);
}
}
It doesn't look very appealing though. What would be the least ugly solution in this situation?
Your solution to not make a subclass is correct one. That is composition, and you should always prefer it over inheritance. So even if A had the right constructor, you shouldn't make B a subclass of A unless you have a specific requirement forcing you to do it.
Only use inheritance when you need to pass instance of B as instance of A. But really, you should rarely need to do that, unless you are dealing with poorly designed code. You should use interfaces, so you would would have class A which implements some interface, let's call it interface IA. Then instead of being subclass of A, you simpley have class B implements IA. And then you have the private member variables of type A inside B, if you need it.
(There's also the matter of when to use interfaces and when to use abstract base classes, but I'll leave it out of this answer.)
Note that modern Java IDEs make creating delegates very easy, and frankly, coding Java without such IDE is wrong way to code Java. Writing all that boilerplate by hand is error-prone, tedious, and makes you hate Java for no reason. With modern IDE, first add that private member variable a, possibly place cursor on it or right click it for context menu, and find "Insert code..." or some such option. From there find something like "Add delegates...". Then you should simply be able to click which methods of A you want to add to B and have them delegated. The IDE should create code in B like this.
int method() {
return a.method();
}
This makes actually following "composition over inheritance" quite nice and easy.

how to extend a class at runtime with reflection

Imagine that I have two Class A and B, B extends A, like
class B extends A
{
....
}
However, in my case, Class A is encrypted and can be only loaded by my ClassLoader at runtime (at compiling time, A.class can not be recognized as a .class file because it is encrypted). This means Class A doesn't exist at compiling time.
My questions are:
how can write the code for Class B, as some methods override the methods in Class A?
how can I specify Class B extends to Class A at runtime?
You can't with reflection. But you can with CGLIB and perhaps javassist
You can create a dummy copy of A which has all the methods you want to override and compile and deploy just B.
If you don't know what methods you want to override until runtime, you will need to generate code using either the Compiler API, however a library like Objectweb's ASM is likely to be much simpler. I prefer ASM because it can easily generate code to generate what you want from a template. i.e. you don't have to write all the code yourself.

Adding functions to Java class libraries

I'm using a Java class library that is in many ways incomplete: there are many classes that I feel ought to have additional member functions built in. However, I am unsure of the best practice of adding these member functions.
Lets call the insufficient base class A.
class A
{
public A(/*long arbitrary arguments*/)
{
//...
}
public A(/*long even more arbitrary arguments*/)
{
//...
}
public int func()
{
return 1;
}
}
Ideally, I would like to add a function to A. However, I can't do that. My choice is between:
class B extends A
{
//Implement ALL of A's constructors here
public int reallyUsefulFunction()
{
return func()+1;
}
}
and
class AddedFuncs
{
public static int reallyUsefulFunction(A a)
{
return a.func()+1;
}
}
The way I see it, they both have advantages and disadvantages. The first choice gives a cleaner syntax than the second, and is more logical, but has problems: Let's say I have a third class, C, within the class library.
class C
{
public A func()
{
return new A(/*...*/);
}
}
As I see it, there is no easy way of doing this:
C c;
int useful = c.func().reallyUsefulFunction();
as the type returned by C.func() is an A, not a B, and you can't down-cast.
So what is the best way of adding a member function to a read-only library class?
Natural and frequent dilemma. Read about the composition vs inheritance alternative. Your second alternative is basically a composition, if we think that the object A is passed in the constructor instead of passing it in each method - that is, we would be using composition to implement a wrapper or decorator pattern.
The issue for class C returning a new instance of class A has no trivial solution, as you guessed, as long as class C decides to take responsability of creating the new instance. This is why one should pause and think before typing a "new" statement inside a class, if there is the possibility that this class will be subclassed. In yout example, it would be nice if you could tell class C what concrete class to return ... but how would it know to create it? Well we could pass him an object who knows how to instantiate an object of class A (or a subclass)... I guess you are enough motivated to read about Factories now, and design patterns in general.
There is no unique best answer, but if want a quick one: I'd make a wrapper, B class does not extend A but has a constructor with A as parameter, it delegates its methods (except the own) to the inside object.
When you need to call the method in class C (I'm assuming you cant touch class C), you could write: B b = new B(c.func())
Why not use Composition instead of Inheritance?
class ABetterA {
private A a;
public ABetterA() {
}
// write wrapper methods calling class' A methods and maybe doing something more
}
This way, you could also mimic multiple inheritance...
You have a third option. You could use Scala (a Java compatible language) and its traits, which are mixins by another name.
Another option similar to Brian's sugestion is to use Aspect Oriented Programming (AOP) tool, such as ApectJ, which let you "inject" additional functionality into existing classes, even binary ones. You either preprocess the library jar to get a new one with enhanced classes ("static weaving") or you can do all of this at runtime when the library classes are loaded (so called "load-time weaving"). You can check this AspectJ example.
Even though AOP is normally used to modify existing methods (before, after or around "advices" = code pieces) you can also introduce new members and methods - check AspectJ's Inter-type declarations.
Of course there is the question whether AspectJ is supported at your limited platform.

Does removing an interface break code calling methods on the object?

I need to do some refactoring in Java, and I need to maintain some degree of binary compatibility. In this case I want to remove some legacy interfaces, that are not used anywhere anymore and which require a rather big (and also deprecated) external dependency.
I have class C that implements interface I, and I have code that calls a method (declared in the interface) on an instance of C. The calling code knows that it is using C, not just the interface.
class C implements I {
void theMethod(){} ; // is declared in the interface I
}
C object;
object.theMethod();
When I remove the interface from the class definition (but keep all the methods), will the calling code (which does not refer to the interface at all) still work (without a recompile)?
Yes, it will work - as long as it doesn't explicitly refer to interface I anywhere.
From JLS: Resolution of Symbolic References:
The binary representation of a class
or interface references other classes
and interfaces and their fields,
methods, and constructors
symbolically, using the binary names
(ยง13.1) of the other classes and
interfaces
Class ClientClass referring to field / method of class C contains no implicit references to interface I that class may implement.
It works as long as an object of class C is never referred to as I.
You can also refer to Evolving Java-based APIs part 2.
You might have a problem with the calling Code if it imports the Interface anywhere. If there is no import of the interface in any of the calling code, you can be reasonably confident that your refactoring will work as planned.

Categories