Java Metaprogramming - java

I'm working on my first real project with Java. I'm beginning to get comfortable with the language, although I have more experience with dynamic languages.
I have a class that behave similar to the following:
class Single
{
public void doActionA() {}
public void doActionB() {}
public void doActionC() {}
}
And then I have a SingleList class that acts as a collection of these classes (specifically, it's for a 2D Sprite library, and the "actions" are all sorts of transformations: rotate, shear, scale, etc). I want to be able to do the following:
class SingleList
{
public void doActionA() {
for (Single s : _innerList) {
s.doActionA();
}
}
... etc ...
}
Is there any way to simply defer a method (or a known list of methods) to each member of the inner list? Any way without having to specifically list each method, then loop through each inner member and apply it manually?
To make things a bit harder, the methods are of varying arity, but are all of return type "void".

Unfortunately Java does not readily support class creation at runtime, which is what you need: the SingleList needs to be automatically updated with the necessary stub methods to match the Single class.
I can think of the following approaches to this issue:
Use Java reflection:
Pros:
It's readily available in the Java language and you can easily find documentation and examples.
Cons:
The SingleList class would not be compatible with the Single class interface any more.
The Java compiler and any IDEs are typically unable to help with methods called via reflection - errors that would be caught by the compiler are typically transformed into runtime exceptions.
Depending of your use case, you might also see a noticeable performance degradation.
Use a build system along with some sort of source code generator to automatically create the SingleList.java file.
Pros:
Once you set it up you will not have to deal with it any more.
Cons:
Setting this up has a degree of difficulty.
You would have to separately ensure that the SingleList class loaded in any JVM - or your IDE, for that matter - actually matches the loaded Single class.
Tackle this issue manually - creating an interface (e.g. SingleInterface) or a base abstract class for use by both classes should help, since any decent IDE will point out unimplemented methods. Proper class architecture would minimize the duplicated code and your IDE might be able to help with generating the boilerplate parts.
Pros:
There is no setup curve to get over.
Your IDE will always see the right set of classes.
The class architecture is usually improved afterwards.
Cons:
Everything is manual.
Use a bytecode generation library such as Javassist or BCEL to dynamically generate/modify the SingleList class on-the-fly.
Pros:
This method is extremely powerful and can save a lot of time in the long term.
Cons:
Using bytecode generation libraries is typically not trivial and not for the faint-hearted.
Depending on how you write your code, you may also have issues with your IDE and its handling of the dynamic classes.

Related

Conditionally Remove Java Methods at Compile-Time

I am trying to achieve something similar to the C# preprocessor. I am aware that Java does NOT have the same preprocessor capabilities, and am aware that there are ways to achieve similar results using design patterns such as Factory. However, I am still interested in finding a solution to this question.
Currently, what I do is create a class that contains several static final boolean attributes, such as the following example:
public class Preprocessor
{
public static final boolean FULLACCESS = false;
}
I then use this in the following manner:
public ClassName getClassName()
{
if(Preprocessor.FULLACCESS)
{
return this;
}
else
{
return this.DeepCopy();
}
}
So far so good, this solves my problem (the example above is trivial, but I do use this in other instances where it is helpful). My question is, would there be a way to place the conditional around an entire method, so that the method itself would be unavailable given the correct "Preprocessor" variables? For example, I would like to be able to make a specific constructor available only for packages that are given "Full Access", as follows:
public ClassName()
{
// do things
}
if(FULLACCESS)
{
public ClassName(ClassName thing)
{
// copy contents from thing to the object being created
}
}
Again, I am aware of the limitations (or design decisions) of Java as a language, and am aware that in most circumstances this is unnecessary. As a matter of fact, I have considered simply creating these "extra" methods and placing the entire code of them within a conditional, while throwing an Exception if the conditional is not active, but that is a very crude solution that does not seem helpful to my programmers when I make these libraries available to them.
Thank you very much in advance for any help.
Edit:
To complement the question, the reason why I am attempting to do this is that by using exceptions as a solution, the IDE would display methods as "available" when they are actually not. However, again, it might just be a case of my being ignorant of Java.
The reasons for my wanting to do this are primarily so that I may have more than one public interface available, say, one restrictive where control is tighter within the methods, and one more permissive where direct alteration of attributes is allowed. However, I do also want to be able to actively remove portions of code from the .class, for instance, in a Product Line development approach where certain variants are not available.
Edit2.:
Furthermore, it is important to note that I will be generating the documentation conditionally as well. Therefore, each compiled version of the packages would have its own documentation, containing only that which is actually available.
Well, you can make it happen. A word of caution, though...
I can only think of one time when I thought this kind of approach was the best way, and it turned out I was wrong. The case of changing a class's public interface especially looks like a red flag to me. Throwing an exception when the access level isn't high enough to invoke the method might be more code-friendly.
But anyway, when I thought I wanted a preprocessor, what I did was to write one. I created a custom annotation to place on conditionally-available methods, grabbed a Java parser and wrote a little program that used the parser to find and remove methods that have the annotation. Then add that (conditionally) to the build process.
Because it turned out to be useless to me, I discarded mine; and I've never seen anyone else do it and publish it; so as far as I know you'd have to roll your own.
This answer is based partially on the comments you have left on the question and on Mark's answer.
I would suggest that you do this using Java interfaces which expose just the API that you desire. When you need a less restrictive API contract, extend an interface or create a separate implementation of an existing interface to get what you need.
public interface A
{
void f();
}
A above is your general API. Now you want to have some special extra methods to test A or to debug it or manipulate it or whatever...
public interface B extends A
{
void specialAccess();
}
Also, Java now supports default method implementations for interfaces which might be useful to you depending on how you implement your API. They take the following form...
public interface A
{
List getList();
// this is still only an interface, but you have a default impl. here
default void add(Object o)
{
getList().add(o);
}
}
You can read more about default methods on Oracle's page about it here.
In your API, your general distribution of it could include A and omit B entirely, and omit any implementations that offer the special access; then you can include B and special implementations for the special access version of the API you mentioned. This would allow plain old Java objects, nothing different to the code other than an extra interface and maybe an extra implementation of it. The custom part would just be in your packaging of the library. If you want to hand someone a "non-special" low-access version, hand them a jar that does not include B and does not include any possible BImplementation, possibly by having a separate build script.
I use Netbeans for my Java work, and I like to let it use the default build scripts that it auto generates. So if I were doing this and I were doing it in Netbeans, I would probably create two projects, one for base API and one for special-access API, and I would make the special-access one dependent on the base project. That would leave me with two jars instead of one, but I would be fine with that; if two jars bothered me enough I would go through the extra step mentioned above of making a build script for the special access version.
Some examples straight from Java
Swing has examples of this kind of pattern. Notice that GUI components have a void paint(Graphics g). A Graphics gives you a certain set of functionality. Generally, that g is actually a Graphics2D, so you can treat it as such if you so desire.
void paint(Graphics g)
{
Graphics2d g2d = Graphics2d.class.cast(g);
}
Another example is with Swing component models. If you use a JList or a JComboBox to display a list of objects in a GUI, you probably do not use the default model it comes with if you want to change that list over time. Instead, you create a new model with added functionality and inject it.
JList list = new JList();
DefaultListModel model = new DefaultListModel();
list.setModel(model);
Now your JList model has extra functionality that is not normally apparent, including the ability to add and remove items easily.
Not only is extra functionality added this way, but the original author of ListModel did not even need to know that this functionality could exist.
the only way in Java to reach that is to use preprocessor, for instance PostgresJDBC team uses java comment preprocessor for such manipulations, here is example from their Driver.java
//#if mvn.project.property.postgresql.jdbc.spec >= "JDBC4.1"
#Override
public java.util.logging.Logger getParentLogger() {
return PARENT_LOGGER;
}
//#endif
With Gradle you can manage your sources and I think that no preprocessor macros are no longer needed. Right now in src directory you have main/java with all sources but if you need specific methods in e.g. debug and release builds to do / or not specific things then create debug/java and release/java in src and put YourClass there. Note that by doing this you'll have to have YourClass in debug/java and release/java but not in main/java.

How Do I Place Auto-generated Java Classes in a Single .java File?

As everyone knows - public java classes must be placed in their own file named [ClassName].java
( When java class X required to be placed into a file named X.java? )
However, we are auto-generating 50+ java classes, and I'd like to put them all in the same file for our convenience. This would make it substantially easier to generate the file(s), and copy them around when we need to.
Is there any way I can get around this restriction? It seems like more of a stylistic concern - and something I might be able to disable with a compiler flag.
If not, what would you recommend?
Can you put wrapper class around your classes? Something like:
public class Wrapper {
public static class A {...}
public static class B {...}
....
}
Then you can access them via Wrapper.A, Wrapper.B.
At the .class level, this is a requirement per the Java spec. Even the inner classes get broken out into their own class file in the from Outer$Inner.class. I believe the same is true at the language level.
Your best bet is to generate the files and make your copy script smart. Perhaps generate them and zip them up. Usually, if you have to move these files around then either everyone has the same generator script OR you distribute them as a JAR.
Is there any way I can get around this restriction?
You can change your generated source code to make it acceptable; e.g. by using nested classes, by putting the generated classes into their own package.
It seems like more of a stylistic concern - and something I might be able to disable with a compiler flag.
It is not just a stylistic concern:
The one file per class rule is allowed by the Java Language Specification.
It is implemented by all mainstream Java compilers.
It is implemented by all mainstream JVMs in the form of the default classloader behavior.
It is assumed by 3rd party Java tools; e.g. IDEs, style checkers, bug checkers, code generation frameworks, etc.
In short, while it would theoretically be legal to implement a Java ecosystem that didn't have this restriction, it is impractical. No such compiler switch exists, and implementing one would be impractical for the reasons above.
The nested class solution is a good one. Another alternative would be to put the generated classes into a separate package (but with separate file) to make them easier to manage.

How to prune a Java program

Let's me start from what I want to do then raising some questions I have.
I want to develop a general Java program which is a superset of a number of programs (let's call them program variants). In particular, the general program has methods which are only used by one or more program variants (but not all). Given a particular configuration, I want to remove unnecessary methods and just keep the smallest set of methods for one program variant.
For example, I have a general program as below:
public class GeneralProgram {
// this method is common for all variants
public void method1() {};
// this method is specific to variant 1
public void method2() {};
// this method is specific to variant 2
public void method3() {};
}
Then after pruning the program based on configuration for variant 1, the result is
public class GeneralProgram {
// this method is common for all variants
public void method1() {};
// this method is specific to variant 1
public void method2() {};
}
It doesn't matter if the resulting class name is the same as the original one or not. I just want to prune the content of the class.
So, here are my questions:
Do you have any idea how to realize this except low level text processing?
I know that I can use aspectJ to disable/enable specific methods at runtime but what I really want to do is performing this task before deploying the program. Is there any technique in Java for this purpose?
It seems to me that the right solution here is to use some object oriented programming and layer your program:
base.jar contains:
package foo.base;
class GeneralProgram {
public void method1(){ }
}
var1.jar contains:
package foo.var1;
import foo.base.GeneralProgram;
class GeneralProgramVar1 extends GeneralProgram {
public void method2(){ }
}
var2.jar contains:
package foo.var2;
import foo.base.GeneralProgram;
class GeneralProgramVar2 extends GeneralProgram {
public void method3(){ }
}
Some deployments will have both base.jar and var1.jar, others will have base.jar and var2.jar. You'll have to mess with the classpaths a bit to resolve the dependencies.
If you can separate your variants well enough so that there are truly unused functions then you can use a compression utility like ProGuard to remove unused methods from the classes. You might find, however, that the effort required to reap the benefits of ProGuard are the same as the structure I recommend above.
#Mark Elliot's answer gives you a "right way" to do this.
There are a number of reasons why your way is not a good idea in general, and for Java applications in particular:
Java does not support this. Specifically, it does not support conditional compilation.
While source code preprocessors are sometimes used, mainstream Java tool chains don't support them. (Same for (hypothetical?) tools that operate at the bytecode level ... though that's not what you seem to be talking about.)
With conditionally compilation variants, it is easier for a change made in one variant to break another. (By contrast, a good O-O design will isolate variant-specific code to particular classes where they can't affect the behaviour of other variants.)
A codebase with rampant conditional compilation is much harder to understand.
Conditional compilation variants make testing more complicated. You basically have to treat each variant as a separate application that has to be tested separately. This makes writing tests more complicated, and running tests more expensive. (And testing the variants IS important because of the fragility of code bases that rely on conditional compilation; see previous.)
Test coverage analysis is harder / more work with variants because of tool issues; see previous.
In a comment the OP writes:
So it is not effective if I deploy unnecessary resources (e.g. methods, classes specific to other variants) for a particular variant.
What do you mean by "not effective"?
In most cases it simply does not matter that a code base includes functionality that is not used in certain use-cases or on certain platforms. Java applications use lots of memory, and code size is generally not the major cause of this. In short, in most cases it is "effective" to deploy code that won't be used: it does the job and the overheads don't really matter.
If you have one of those unusual applications where JAR file size or code memory usage is really significant (and not just a hypothetical issue), you still don't need to resort to conditional compilation or bytecode hacking.
If JAR file size is the critical issue, then there are tools that will strip out classes and methods that the tool determines will not be used; e.g. assuming that the application is started from a specified main method.
If memory usage is the critical issue, you can structure your code so that it uses dynamic loading to load variant, platform or even use-case specific classes.

C++ and Java : Use of virtual base class

I have some doubts while comparing C++ and Java multiple inheritance.
Even Java uses multiple, multi-level inheritance through interfaces - but why doesnt it use anything like a virtual base class as in C++ ? Is it because the members of a java interface are being ensured one copy in memory (they are public static final), and the methods are only declared and not defined ?
Apart from saving memory, is there any other use of virtual classes in C++ ? Are there any caveats if I forget to use this feature in my multiple inheritance programs ?
This one is a bit philosophical - but why didnt the C++ developers made it a default to make every base class, virtual ? What was the need of providing flexibility ?
Examples will be appreciated. Thanks !!
1) Java interfaces dont have attributes. One reason for virtual base classes in c++ is to prevent duplicate attributes and all the difficulties associated with that.
2) There is at least a slight performance penalty for using virtual base classes in c++. Also, the constructors become so complicated, that it is advised that virtual base classes only have no-argument constructors.
3) Exactly because of the c++ philosphy: One should not require a penalty for something which one may not need.
Sorry - not a Java programmer, so short on details. Still, virtual bases are a refinement of multiple inheritance, which Java designers always defended ommiting on the basis that it's overly complicated and arguably error-prone.
virtual bases aren't just for saving memory - the data is shared by the different objects inheriting from them, so those derived types could use it to coordinate their behaviour in some way. They're not useful all that often, but as an example: object identifiers where you want one id per most-derived object, and not to count all the subobjects. Another example: ensuring that a multiply-derived type can unambiguously map / be converted to a pointer-to-base, keeping it easy to use in functions operating on the base type, or to store in containers of Base*.
As C++ is currently Standardised, a type deriving from two classes can typically expect them to operate independently and as objects of that type tend to do when created on the stack or heap. If everything was virtual, suddenly that independence becomes highly dependent on the types from which they happen to be derived - all sorts of interactions become the default, and derivation itself becomes less useful. So, your question is why not make the default virtual - well, because it's the less intuitive, more dangerous and error-prone of the two modes.
1.Java multiple inheritance in interfaces behaves most like virtual inheritance in C++.
More precisely, to implement java-like inheritance model in c++ you need to use c++ virtual base classes.
However, one of the disadvantages of c++ virtual inheriritance (except of small memory and performance penalty) is the impossibility to static_cast<> from base to derived, so rtti (dynamic_cast) need to be used
(or one may provide "hand made" virtual casting functions for child classes if a list of
such child classes are known in advance)
2.if you forget "virtual" qualifier in inheritance list, it usually lead to compiler error
since any casting frome drived to base class becomes ambigious
3.Philosophical questions usually are quite dificult to answer... c++ is a multiparadigm (and multiphilosophical) language and doesn't impose any philosophical decisions. You may use virtual inheritance whenever possible in you own projects, and (you are rioght) it has a good reason. But such a maxima may be unacceptable for others, so universal c++ tools (standard and other widely used libraries) should be (if possible) free of any particular philosophical conventions.
I'm working on an open source project which basically is translating a large C++ library to Java. The object model of the original creature in C++ can be pretty complicated sometimes. More than necessary, I'd say... which was more or less the motto of Java designers... well... this is another subject.
The point is that I've written an article which shows how you can circumvent type erasure in Java. The article explains well how it can be done and, in the end how your source code can eventually resemble C++ very closely.
http://www.jquantlib.org/index.php/Using_TypeTokens_to_retrieve_generic_parameters
An immediate implication of the study I've done is that it would be possible to implement virtual base classes in your application, I mean: not in Java, not in the language, but in your application, via some tricks, or a lot of tricks to be more precise.
In case you do have interest for such kind of black magic, the lines below may be useful for you somehow. Otherwise certainly not.
Ok. Let's go ahead.
There are several difficulties in Java:
1. Type erasure (solved in the article)
2. javac was not designed to understand what a virtual base class would be;
3. Even using tricks you will not be able to circumvent difficulty #2, because this difficulty appears at compilation time.
If you'd like to use virtual base classes, you can have it with Scala, which basically solved difficulty #2 by exactly creating another compiler, which fully understands some more sophisticated object models, I'd say.
if you'd like to explore my article and try to "circunvent" virtual base classes in pure Java (not Scala), you could do something like I explain below:
Suppose that you have something like this in C++:
template<Base>
public class Extended : Base { ... }
It could be translate to something like this in Java:
public interface Virtual<T> { ... }
public class Extended<B> implements Virtual<B> { ... }
OK. What happens when you instantiate Extended like below?
Extended extended = new Extended<Base>() { /* required anonymous block here */ }
Well.. basically you will be able to get rid of type erasure and will be able to Obtain type information of Base inside your class Extended. See my article for a comprehensive explanation of the black magic.
OK. Once you have type of Base inside Extended, you can instantiate a concrete implementation of Virtual.
Notice that, at compile time, javac can verify types for you, like in the example below:
public interface Virtual<Base> {
public List<Base> getList();
}
public class Extended<Base> implements Virtual<Base> {
#Override
public List<Base> getList() {
// TODO Auto-generated method stub
return null;
}
}
Well... despite all effort to implement it, in the end we are doing badly what an excellent compiler like scalac does much better than us, in particular it is doing its job at compile time.
I hope it helps... if not confused you already!

Explicit typing in Groovy: sometimes or never?

[Later: Still can't figure out if Groovy has static typing (seems that it does not) or if the bytecode generated using explicit typing is different (seems that it is). Anyway, on to the question]
One of the main differences between Groovy and other dynamic languages -- or at least Ruby -- is that you can statically explicitly type variables when you want to.
That said, when should you use static typing in Groovy? Here are some possible answers I can think of:
Only when there's a performance problem. Statically typed variables are faster in Groovy. (or are they? some questions about this link)
On public interfaces (methods, fields) for classes, so you get autocomplete. Is this possible/true/totally wrong?
Never, it just clutters up code and defeats the purpose of using Groovy.
Yes when your classes will be inherited or used
I'm not just interested in what YOU do but more importantly what you've seen around in projects coded in Groovy. What's the norm?
Note: If this question is somehow wrong or misses some categories of static-dynamic, let me know and I'll fix it.
In my experience, there is no norm. Some use types a lot, some never use them. Personally, I always try to use types in my method signatures (for params and return values). For example I always write a method like this
Boolean doLogin(User user) {
// implementation omitted
}
Even though I could write it like this
def doLogin(user) {
// implementation omitted
}
I do this for these reasons:
Documentation: other developers (and myself) know what types will be provided and returned by the method without reading the implementation
Type Safety: although there is no compile-time checking in Groovy, if I call the statically typed version of doLogin with a non-User parameter it will fail immediately, so the problem is likely to be easy to fix. If I call the dynamically typed version, it will fail some time after the method is invoked, and the cause of the failure may not be immediately obvious.
Code Completion: this is particularly useful when using a good IDE (i.e. IntelliJ) as it can even provide completion for dynamically added methods such as domain class' dynamic finders
I also use types quite a bit within the implementation of my methods for the same reasons. In fact the only times I don't use types are:
I really want to support a wide range of types. For example, a method that converts a string to a number could also covert a collection or array of strings to numbers
Laziness! If the scope of a variable is very short, I already know which methods I want to call, and I don't already have the class imported, then declaring the type seems like more trouble than it's worth.
BTW, I wouldn't put too much faith in that blog post you've linked to claiming that typed Groovy is much faster than untyped Groovy. I've never heard that before, and I didn't find the evidence very convincing.
I worked on a several Groovy projects and we stuck to such conventions:
All types in public methods must be specified.
public int getAgeOfUser(String userName){
...
}
All private variables are declared using the def keyword.
These conventions allow you to achieve many things.
First of all, if you use joint compilation your java code will be able to interact with your groovy code easily. Secondly, such explicit declarations make code in large projects more readable and sustainable. And of-course auto-completion is an important benefit too.
On the other hand, the scope of a method is usually quite small that you don't need to declare types explicitly. By the way, modern IDEs can auto-complete your local variables even if you use defs.
I have seen type information used primarily in service classes for public methods. Depending on how complex the parameter list is, even here I usually see just the return type typed. For example:
class WorkflowService {
....
WorkItem getWorkItem(processNbr) throws WorkflowException {
...
...
}
}
I think this is useful because it explicitly tells the user of the service what type they will be dealing with and does help with code assist in IDE's.
Groovy does not support static typing. See it for yourself:
public Foo func(Bar bar) {
return bar
}
println("no static typing")
Save and compile that file and run it.

Categories