Initialize (load) a java class with a java.lang.Class<T> instance - java

I have to admit that this is more a cosmetic issue, but the fact that I haven't found a more straight-forward solution makes me think I am probably missing something.
The thing is, my class (let's say Foo) has a very important static block where it registers itself (Foo.class) with a builder method in a Map, like this:
// somewhere in the class
static {
Bar.registerBuilder(Foo.class, Foo::build);
}
This makes it possibe to get a Foo builder from the Bar class, a bit like this:
// somewhere in a method
Foo foo = Bar.getBuilder(Foo.class).apply("Hello World");
(if the builder takes a String argument). However, the upper code example will only work if the Foo class was already initialized. If not, this means the static block of Foo wasn't executed and the builder isn't registered in Bar by now, which is leading to getBuilder() returning null and apply() throwing a NullPointerException.
Thanks to the internet (mostly StackOverflow) I found out that you can imperatively with Class.forName(String). But what really confuses me is that this method takes a String (therefore throws the checked ClassNotFoundException) and I haven't found a way to load and initialize a class directly via a java.lang.Class instance. I would have expected something like
Class<Foo> clazz = Foo.class;
clazz.load(); // does not exist
Instead I have to do this:
Class<Foo> clazz = Foo.class;
try {
Class.forName(clazz.getName());
} catch (ClassNotFoundException) {
// handle an exception that is actually unreachable
}
I would like to know if I am completely missing something, or if not, if there is a cleaner way to load and initialize a class via the java.lang.Class representation.
Any help is appreciated, thank you!
EDIT 1: As #Boris the Spider pointed out in the comments, Foo.class should probably already load and initialize the class, but it doesn't (in my case, at least) and that's why I even encountered this problem.
EDIT 2: Using the "complicated" way to load the class via Class.forName() (as in the code example) actually resolves the problem as I thought. It's just that I'd like to use a cleaner way if possible.
Using:
Java 11 (openjdk 11.0.2)
IntelliJ IDEA Ultimate (2019.3)
Maven (3.6.3)

If you are already referencing the class it would be much better to move that static code into normal static factory method. As why would you use reflections or try to reference some class just to make some code run when you can just run that method?
public static BuilderFunction createBuilder() {
return Foo::build;
}
And just call it in static block of Bar:
registerBuilder(Foo.class, Foo.createBuilder());
If you need something more dynamic you can use service loaders, especially with java 9+ as they are much nicer now to use:
provides my.BuilderProvder with something.FooProvider;
And just load them all in Bar:
ServiceLoader<BuilderProvder> loader = ServiceLoader.load(BuilderProvder.class);
loader.stream()
.forEach(provider -> registerBuilder(provider));
now even different modules not developed by you can provide own builders and you don't need to do any manual class loading (and class initialization is only guaranteed to happen if class is actually used, like some method or field used - note that constants are inlined at compilation so they don't count).
You can also use some hacky reflection libraries like ClassGraph or Reflections to get all classes of given type/with given annotation and then load them and invoke some init method on them all just like in my first proposed solution with createBuilder. This is how many components inside spring are registered, similar thing can be done with java annotation preprocessing to find this classes at compile time and just save the names. But if possible I would suggest sticking to existing build in solutions like service loaders.

Related

Calling static methods using an instance of that class [duplicate]

I'm sure you all know the behaviour I mean - code such as:
Thread thread = new Thread();
int activeCount = thread.activeCount();
provokes a compiler warning. Why isn't it an error?
EDIT:
To be clear: question has nothing to do with Threads. I realise Thread examples are often given when discussing this because of the potential to really mess things up with them. But really the problem is that such usage is always nonsense and you can't (competently) write such a call and mean it. Any example of this type of method call would be barmy. Here's another:
String hello = "hello";
String number123AsString = hello.valueOf(123);
Which makes it look as if each String instance comes with a "String valueOf(int i)" method.
Basically I believe the Java designers made a mistake when they designed the language, and it's too late to fix it due to the compatibility issues involved. Yes, it can lead to very misleading code. Yes, you should avoid it. Yes, you should make sure your IDE is configured to treat it as an error, IMO. Should you ever design a language yourself, bear it in mind as an example of the kind of thing to avoid :)
Just to respond to DJClayworth's point, here's what's allowed in C#:
public class Foo
{
public static void Bar()
{
}
}
public class Abc
{
public void Test()
{
// Static methods in the same class and base classes
// (and outer classes) are available, with no
// qualification
Def();
// Static methods in other classes are available via
// the class name
Foo.Bar();
Abc abc = new Abc();
// This would *not* be legal. It being legal has no benefit,
// and just allows misleading code
// abc.Def();
}
public static void Def()
{
}
}
Why do I think it's misleading? Because if I look at code someVariable.SomeMethod() I expect it to use the value of someVariable. If SomeMethod() is a static method, that expectation is invalid; the code is tricking me. How can that possibly be a good thing?
Bizarrely enough, Java won't let you use a potentially uninitialized variable to call a static method, despite the fact that the only information it's going to use is the declared type of the variable. It's an inconsistent and unhelpful mess. Why allow it?
EDIT: This edit is a response to Clayton's answer, which claims it allows inheritance for static methods. It doesn't. Static methods just aren't polymorphic. Here's a short but complete program to demonstrate that:
class Base
{
static void foo()
{
System.out.println("Base.foo()");
}
}
class Derived extends Base
{
static void foo()
{
System.out.println("Derived.foo()");
}
}
public class Test
{
public static void main(String[] args)
{
Base b = new Derived();
b.foo(); // Prints "Base.foo()"
b = null;
b.foo(); // Still prints "Base.foo()"
}
}
As you can see, the execution-time value of b is completely ignored.
Why should it be an error? The instance has access to all the static methods. The static methods can't change the state of the instance (trying to is a compile error).
The problem with the well-known example that you give is very specific to threads, not static method calls. It looks as though you're getting the activeCount() for the thread referred to by thread, but you're really getting the count for the calling thread. This is a logical error that you as a programmer are making. Issuing a warning is the appropriate thing for the compiler to do in this case. It's up to you to heed the warning and fix your code.
EDIT: I realize that the syntax of the language is what's allowing you to write misleading code, but remember that the compiler and its warnings are part of the language too. The language allows you to do something that the compiler considers dubious, but it gives you the warning to make sure you're aware that it could cause problems.
They cannot make it an error anymore, because of all the code that is already out there.
I am with you on that it should be an error.
Maybe there should be an option/profile for the compiler to upgrade some warnings to errors.
Update: When they introduced the assert keyword in 1.4, which has similar potential compatibility issues with old code, they made it available only if you explicitly set the source mode to "1.4". I suppose one could make a it an error in a new source mode "java 7". But I doubt they would do it, considering that all the hassle it would cause. As others have pointed out, it is not strictly necessary to prevent you from writing confusing code. And language changes to Java should be limited to the strictly necessary at this point.
Short answer - the language allows it, so its not an error.
The really important thing, from the compiler's perspective, is that it be able to resolve symbols. In the case of a static method, it needs to know what class to look in for it -- since it's not associated with any particular object. Java's designers obviously decided that since they could determine the class of an object, they could also resolve the class of any static method for that object from any instance of the object. They choose to allow this -- swayed, perhaps, by #TofuBeer's observation -- to give the programmer some convenience. Other language designers have made different choices. I probably would have fallen into the latter camp, but it's not that big of a deal to me. I probably would allow the usage that #TofuBeer mentions, but having allowed it my position on not allowing access from an instance variable is less tenable.
Likely for the same logical that makes this not an error:
public class X
{
public static void foo()
{
}
public void bar()
{
foo(); // no need to do X.foo();
}
}
It isn't an error because it's part of the spec, but you're obviously asking about the rationale, which we can all guess at.
My guess is that the source of this is actually to allow a method in a class to invoke a static method in the same class without the hassle. Since calling x() is legal (even without the self class name), calling this.x() should be legal as well, and therefore calling via any object was made legal as well.
This also helps encourage users to turn private functions into static if they don't change the state.
Besides, compilers generally try to avoid declaring errors when there is no way that this could lead to a direct error. Since a static method does not change the state or care about the invoking object, it does not cause an actual error (just confusion) to allow this. A warning suffices.
The purpose of the instance variable reference is only to supply the type which encloses the static. If you look at the byte code invoking a static via instance.staticMethod or EnclosingClass.staticMethod produces the same invoke static method bytecode. No reference to the instance appears.
The answer as too why it's in there, well it just is. As long as you use the class. and not via an instance you will help avoid confusion in the future.
Probably you can change it in your IDE (in Eclipse Preferences -> Java -> Compiler -> Errors/Warnings)
There's not option for it. In java (like many other lang.) you can have access to all static members of a class through its class name or instance object of that class. That would be up to you and your case and software solution which one you should use that gives you more readability.
It's pretty old topic but still up-to-date and surprisingly bringing higher impact nowadays. As Jon mentioned, it might be just a mistake Java's designers made at the very beginning. But I wouldn't imagine before it can have impact on security.
Many coders know Apache Velocity, flexible and powerful template engine. It's so powerful that it allows to feed template with a set of named objects - stricly considered as objects from programming language (Java originally). Those objects can be accessed from within template like in programming language so for example Java's String instance can be used with all its public fields, properties and methods
$input.isEmpty()
where input is a String, runs directly through JVM and returns true or false to Velocity parser's output). So far so good.
But in Java all objects inherit from Object so our end-users can also put this to the template
$input.getClass()
to get an instance of String Class.
And with this reference they can also call a static method forName(String) on this
$input.getClass().forName("java.io.FileDescriptor")
use any class name and use it to whatever web server's account can do (deface, steal DB content, inspect config files, ...)
This exploit is somehow (in specific context) described here: https://github.com/veracode-research/solr-injection#7-cve-2019-17558-rce-via-velocity-template-by-_s00py
It wouldn't be possible if calling static methods from reference to the instance of class was prohibited.
I'm not saying that a particular programming framework is better than the other one or so but I just want to put a comparison. There's a port of Apache Velocity for .NET. In C# it's not possible to call static methods just from instance's reference what makes exploit like this useless:
$input.GetType().GetType("System.IO.FileStream, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
I just consider this:
instanceVar.staticMethod();
to be shorthand for this:
instanceVar.getClass().staticMethod();
If you always had to do this:
SomeClass.staticMethod();
then you wouldn't be able to leverage inheritance for static methods.
That is, by calling the static method via the instance you don't need to know what concrete class the instance is at compile time, only that it implements staticMethod() somewhere along the inheritance chain.
EDIT: This answer is wrong. See comments for details.

How can I intercept a call from Java to Groovy--or simulate this easily

I was hoping to use groovy's invokeMethod to do this, but it turns out that when you call from Java to Groovy, invokeMethod isn't called, but otherwise it would have worked perefectly.
I have a case where I'm submitting a Groovy class to a Java class (Which I can't edit). The Groovy class is annotated and the Java class scans for the annotations and saves the annotated methods as listeners for it's events.
When the event is issued I'd like to grab some information from the event object, use it to retrieve data and inject that data into the event handler in the script (Via annotated variables inside that method).
The things I have control over--I instantiate the scripts, set a base class for them, and pass them to the other system to be registered. The scripts will be written by others--I have control over the script's design but my goal is simplicity.
I could probably create an adapter class, but that seems quite difficult and fragile since I'd have to manually register all those methods instead of using the annotations like it does now--there are a lot of different events to listen to.
I'm wondering if there are groovy tricks I'm not considering. I'm still pretty new to groovy meta-programming. Perhaps there is a way to create the adapter class automatically, or when I compile the scripts, replace the methods with forwarding methods that forward to my code before calling their real method--anything like that possible?
Requested source code:
Source code--well let's see, this process is spread across a few classes...
This is how I set up the Groovy Class Loader with a ScriptBase
cconfig.setScriptBaseClass("tv.kress.bill.minecraft.ezplugin.ScriptBase");
GroovyClassLoader gcl = new GroovyClassLoader(getClass().getClassLoader(), cconfig);
Then I pass it to the Groovy Scripting Engine (I'm leaving out some stuff here)
gse = new GroovyScriptEngine(cpString, gcl);
Then I instantiate the script
scriptClass = gse.loadScriptByName(file.getAbsolutePath());
instance = (GroovyObject) scriptClass.newInstance();
Then, if it's a "Listener" which is the marker interface that the "canned" java library uses to identify java classes it should scan for annotations, I pass it off to that class so that any annotated methods can be registered (Somewhere along the line "instance" became "script", same object though:
if (script instanceof Listener)
pm.registerEvents((Listener) script, this);
The interesting part of the script itself looks like this:
#EventHandler
public void userEvent(UserInteractEvent event) {
What I'd like to add is the ability to, inside the userEvent, add an annotated local variable like this:
#Persist int persistedPerUserData // Or #PersistPerUser? or #Persist(User=true)?
so that just before userEvent is called, I can intercept it. I'd grab the user name from the UserInteractionEvent, combine it with the script, variable and method name to get a unique signature like "MyScript:UserEvent:Bill:persistedPerUserData" and use that to retrieve an int I can place into persistedPerUserData.
Later after the method returns grab the value from persistedPerUserData and store it back into "MyScript:UserEvent:Bill:persistedPerUserData" (Currently a hash but I expect to make it a database eventually).
In this way, the script never has to consider the fact that it's dealing with different users, it just has to have a single set of variables and all the persistence just works.
There are other events this will work for, but I believe they all extend the same event and that root event has the "user" field.
EDIT: Just as another thing NOT to try, I tried to use the ProxyMetaClass/interceptor like this:
// Attempt (and fail) to intercept calls to an instance of clazz
class Slicer {
public static Object slice(Class clazz) {
Object instance;
def proxy = ProxyMetaClass.getInstance(clazz);
proxy.interceptor = new MyInterceptor();
proxy.use {
instance = clazz.newInstance();
}
return instance;
}
}
With the same results, every call from a groovy class was instrumented fine, but no calls from Java were intercepted. Back to the drawing board. I guess this is why Aspects use bytecode manipulation.
I really haven't figured out an answer to this, but I came up with something that I think will work--I suppose nobody mentioned it because it was so obvious, but I'm still "Thinking in Java" More than groovy.
Okay, where I was hoping for the script implementation to look something like this:
#EventHandler
public void userEvent(UserInteractEvent event) {
#Persist int persisteData
// At this point persistedData contains data different depending on which user was passed in
...
I think that if I use a closure I think I can do something close:
#EventHandler
public void userEvent(UserInteractEvent event) {
persistScope(event.user) {
#Persist int persistedPerUserData // Or #PersistPerUser? or #Persist(User=true)?
...
and that way within persistScope I can scan the closure for #Persist annotations and do my thing. This may not work exactly because that int hasn't been created until the closure starts, but I think I can fix that using the methods I mentioned in the question as long as I'm calling from groovy to groovy. Either that or I'll just make "it" a hash with the persisted user data.
It's slightly more awkward but I think it will work, and I like the fact that it's a little more explicit (In fact before I was just assuming that the "event" passed in had a .getUser() method, now I can scope persistence to anything I want).
I'll go try to implement this and give it a few days to see if anyone comes up with an answer to the original question I asked before accepting this.
EDIT: I'm unhappy with this solution. Since the variables are declared inside that scope I couldn't use the #Persist annotation, so i passed in a hash that the module can use as a data container, then I persist it after the closure returns.
Still looking for better answers...

Equivalent of #define in Java?

I'm writing a library that needs to have some code if a particular library is included. Since this code is scattered all around the project, it would be nice if users didn't have to comment/uncomment everything themselves.
In C, this would be easy enough with a #define in a header, and then code blocks surrounded with #ifdefs. Of course, Java doesn't have the C preprocessor...
To clarify - several external libraries will be distributed with mine. I do not want to have to include them all to minimize my executable size. If a developer does include a library, I need to be able to use it, and if not, then it can just be ignored.
What is the best way to do this in Java?
There's no way to do what you want from within Java. You could preprocess the Java source files, but that's outside the scope of Java.
Can you not abstract the differences and then vary the implementation?
Based on your clarification, it sounds like you might be able to create a factory method that will return either an object from one of the external libraries or a "stub" class whose functions will do what you would have done in the "not-available" conditional code.
As other have said, there is no such thing as #define/#ifdef in Java. But regarding your problem of having optional external libraries, which you would use, if present, and not use if not, using proxy classes might be an option (if the library interfaces aren't too big).
I had to do this once for the Mac OS X specific extensions for AWT/Swing (found in com.apple.eawt.*). The classes are, of course, only on the class-path if the application is running on Mac OS. To be able to use them but still allow the same app to be used on other platforms, I wrote simple proxy classes, which just offered the same methods as the original EAWT classes. Internally, the proxies used some reflection to determine if the real classes were on the class-path and would pass through all method calls. By using the java.lang.reflect.Proxy class, you can even create and pass around objects of a type defined in the external library, without having it available at compile time.
For example, the proxy for com.apple.eawt.ApplicationListener looked like this:
public class ApplicationListener {
private static Class<?> nativeClass;
static Class<?> getNativeClass() {
try {
if (ApplicationListener.nativeClass == null) {
ApplicationListener.nativeClass = Class.forName("com.apple.eawt.ApplicationListener");
}
return ApplicationListener.nativeClass;
} catch (ClassNotFoundException ex) {
throw new RuntimeException("This system does not support the Apple EAWT!", ex);
}
}
private Object nativeObject;
public ApplicationListener() {
Class<?> nativeClass = ApplicationListener.getNativeClass();
this.nativeObject = Proxy.newProxyInstance(nativeClass.getClassLoader(), new Class<?>[] {
nativeClass
}, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
ApplicationEvent event = new ApplicationEvent(args[0]);
if (methodName.equals("handleReOpenApplication")) {
ApplicationListener.this.handleReOpenApplication(event);
} else if (methodName.equals("handleQuit")) {
ApplicationListener.this.handleQuit(event);
} else if (methodName.equals("handlePrintFile")) {
ApplicationListener.this.handlePrintFile(event);
} else if (methodName.equals("handlePreferences")) {
ApplicationListener.this.handlePreferences(event);
} else if (methodName.equals("handleOpenFile")) {
ApplicationListener.this.handleOpenFile(event);
} else if (methodName.equals("handleOpenApplication")) {
ApplicationListener.this.handleOpenApplication(event);
} else if (methodName.equals("handleAbout")) {
ApplicationListener.this.handleAbout(event);
}
return null;
}
});
}
Object getNativeObject() {
return this.nativeObject;
}
// followed by abstract definitions of all handle...(ApplicationEvent) methods
}
All this only makes sense, if you need just a few classes from an external library, because you have to do everything via reflection at runtime. For larger libraries, you probably would need some way to automate the generation of the proxies. But then, if you really are that dependent on a large external library, you should just require it at compile time.
Comment by Peter Lawrey: (Sorry to edit, its very hard to put code into a comment)
The follow example is generic by method so you don't need to know all the methods involved. You can also make this generic by class so you only need one InvocationHandler class coded to cover all cases.
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
ApplicationEvent event = new ApplicationEvent(args[0]);
Method method = ApplicationListener.class.getMethod(methodName, ApplicationEvent.class);
return method.invoke(ApplicationListener.this, event);
}
In Java one could use a variety of approaches to achieve the same result:
Dependency Injection
Annotations
Reflection
The Java way is to put behaviour that varies into a set of separate classes abstracted through an interface, then plug the required class at run time. See also:
Factory pattern
Builder pattern
Strategy pattern
Well, Java syntax is close enough to C that you could simply use the C preprocessor, which is usually shipped as a separate executable.
But Java isn't really about doing things at compile time anyway. The way I've handled similar situations before is with reflection. In your case, since your calls to the possibly-non-present library are scattered throughout the code, I would make a wrapper class, replace all the calls to the library with calls to the wrapper class, and then use reflection inside the wrapper class to invoke on the library if it is present.
Use a constant:
This week we create some constants
that have all of the benefits of using
the C preprocessor's facilities to
define compile-time constants and
conditionally compiled code.
Java has gotten rid of the entire
notion of a textual preprocessor (if
you take Java as a "descendent" of
C/C++). We can, however, get the best
benefits of at least some of the C
preprocessor's features in Java:
constants and conditional compilation.
I don't believe that there really is such a thing. Most true Java users will tell you that this is a Good Thing, and that relying on conditional compilation should be avoided at almost all costs.
I'm don't really agree with them...
You CAN use constants that can be defined from the compile line, and that will have some of the effect, but not really all. (For example, you can't have things that don't compile, but you still want, inside #if 0... (and no, comments don't always solve that problem, because nesting comments can be tricky...)).
I think that most people will tell you to use some form of inheritance to do this, but that can be very ugly as well, with lots of repeated code...
That said, you CAN always just set up your IDE to throw your java through the pre-processor before sending it to javac...
"to minimize my executable size"
What do you mean by "executable size"?
If you mean the amount of code loaded at runtime, then you can conditionally load classes through the classloader. So you distribute your alternative code no matter what, but it's only actually loaded if the library that it stands in for is missing. You can use an Adapter (or similar) to encapsulate the API, to make sure that almost all of your code is exactly the same either way, and one of two wrapper classes is loaded according to your case. The Java security SPI might give you some ideas how this can be structured and implemented.
If you mean the size of your .jar file, then you can do the above, but tell your developers how to strip the unnecessary classes out of the jar, in the case where they know they aren't going to be needed.
I have one more best way to say.
What you need is a final variable.
public static final boolean LibraryIncluded= false; //or true - manually set this
Then inside the code say as
if(LibraryIncluded){
//do what you want to do if library is included
}
else
{
//do if you want anything to do if the library is not included
}
This will work as #ifdef. Any one of the blocks will be present in the executable code. Other will be eliminated in the compile time itself
Use properties to do this kind of thing.
Use things like Class.forName to identify the class.
Do not use if-statements when you can trivially translate a property directly to a class.
Depending on what you are doing (not quite enough information) you could do something like this:
interface Foo
{
void foo();
}
class FakeFoo
implements Foo
{
public void foo()
{
// do nothing
}
}
class RealFoo
{
public void foo()
{
// do something
}
}
and then provide a class to abstract the instantiation:
class FooFactory
{
public static Foo makeFoo()
{
final String name;
final FooClass fooClass;
final Foo foo;
name = System.getProperty("foo.class");
fooClass = Class.forName(name);
foo = (Foo)fooClass.newInstance();
return (foo);
}
}
Then run java with -Dfoo.name=RealFoo|FakeFoo
Ignored the exception handling in the makeFoo method and you can do it other ways... but the idea is the same.
That way you compile both versions of the Foo subclasses and let the developer choose at runtime which they wish to use.
I see you specifying two mutually exclusive problems here (or, more likely, you have chosen one and I'm just not understanding which choice you've made).
You have to make a choice: Are you shipping two versions of your source code (one if the library exists, and one if it does not), or are you shipping a single version and expecting it to work with the library if the library exists.
If you want a single version to detect the library's existence and use it if available, then you MUST have all the code to access it in your distributed code--you cannot trim it out. Since you are equating your problem with using a #define, I assumed this was not your goal--you want to ship 2 versions (The only way #define can work)
So, with 2 versions you can define a libraryInterface. This can either be an object that wraps your library and forwards all the calls to the library for you or an interface--in either case this object MUST exist at compile time for both modes.
public LibraryInterface getLibrary()
{
if(LIBRARY_EXISTS) // final boolean
{
// Instantiate your wrapper class or reflectively create an instance
return library;
}
return null;
}
Now, when you want to USE your library (cases where you would have had a #ifdef in C) you have this:
if(LIBRARY_EXISTS)
library.doFunc()
Library is an interface that exists in both cases. Since it's always protected by LIBRARY_EXISTS, it will compile out (should never even load into your class loader--but that's implementation dependent).
If your library is a pre-packaged library provided by a 3rd party, you may have to make Library a wrapper class that forwards it's calls to your library. Since your library wrapper is never instantiated if LIBRARY_EXISTS is false, it shouldn't even be loaded at runtime (Heck, it shouldn't even be compiled in if the JVM is smart enough since it's always protected by a final constant.) but remember that the wrapper MUST be available at compile time in both cases.
If it helps have a look at j2me polish or Using preprocessor directives in BlackBerry JDE plugin for eclipse?
this is for mobiles app but this can be reused no ?

Java static reflection on subclasses

I am implementing a sort of ORM in Java. I am trying to do a static find method that is only in the parent class. Let me get to the point:
public class DB {
public static Object find (int id) {
// i want to return anew instance of the calling subclass
}
}
public class Item extends DB {
// nothing here
}
public class Test {
public static void main () {
Item i = (Item) Item.find(2);
...
}
}
I don't know how to have the find method know which of its inherited class is calling it, so that i can return the right instance (and maybe call the right constructor, etc.) And the inherited class could be anything, no limit.
I've tried stacktrace, but it's only traced from Test to DB.
Any ideas?
Thank you everyone!
Static methods are not inherited, so you can't do this. A common approach to this problem (not including using one of tons of available ORM solutions) is to split your class hierarchy into two:
"Entity" (e.g. classes representing your actual data)
and "DAO" (Data Access Object) - classes that contain methods to manipulate data persistence.
A word to the wise: It's probably a bad idea to try and implement your own ORM. Projects like hibernate have covered this task in great detail, so if you roll your own you are likely to reinvent the wheel and possibly attempt to solve problems that have already been solved.
More on topic, ChssPly76 is correct in that you cannot accomplish this because of how static methods are handled in Java. When the VM loads the bytecode for the static method invocation, it will perform a lookup to find where the method actually is located. It won't find it on the Item class, so it will instead bind the call to DB.find.
However! It may be possible to achieve what you are trying to do with some bytecode wrangling. Viewing the bytecode (using javap -c) for the static method call in your example, we get the following:
invokestatic Method Item.find:(I)Ljava/lang/Object
Thus, once your call reaches DB.find, you could follow the stacktrace back to the callsite, and then inspect the bytecode at the callsite to retrive the actual target of the call. In theory, anyway, as I haven't seen this myself in practice. Also, beware of hacking bytecode like this, for here be dragons.
Kudos for identifying the active record pattern, and wanting to use it in Java. I do agree it's a design pattern that makes more sense than most DB access patterns found in Java, and it's one of the strengths of Ruby and PHP.
I think you may find the "Generic DAO" article at IBM developerworks useful.
Short: use Generics wisely.

In Java, how do I ensure a dummy class is never used?

I am working on a project in which, to resolve a versioning issue, I am creating many classes which will never be tested and must not ever be used - they just need to be there to keep the compiler happy. I'd like to make sure they are never used. This morning I had the idea of throwing an exception in a static initialization block:
public class Dummy {
static {
throw new IllegalStateException("Do not use this class!");
}
}
But the compiler doesn't like it. Can you think of any way to do this?
EDIT: to be clear (my fault I wasn't clear before), these won't just be empty classes. There will be all sorts of code in here, and by "keep the compiler happy" I did indeed mean that elsewhere I will be instantiating them, calling methods etc etc. I want this code elsewhere to compile but fail at runtime. I have accepted Jon's answer but will also be using #Deprecated and documenting extensively as appropriate.
#Deprecated
A program element annotated #Deprecated is one that programmers are discouraged from using, typically because it is dangerous, or because a better alternative exists. Compilers warn when a deprecated program element is used or overridden in non-deprecated code.
Just add a dummy condition:
public class Dummy {
static {
if (true) {
throw new IllegalStateException("Do not use this class!");
}
}
}
I'm not really sure I like this, but it may do what you want it to. Are you sure there's no alternatively which would let you get away without having a completely useless class like this?
Give it a private default constructor, and make the class final.
Assuming you don't want IllegalStateExceptions potentially being thrown in your production code, use assertions and make sure they are enabled on your QA/Test environment. The code is slightly nicer too:
public class Dummy {
static {
//This class should never be initialised!
assert false : "This class should never be initialised";
}
...
}
You may get around the compiler with something like:
public class Dummy {
static {
if (true)
throw new IllegalStateException("Do not use this class!");
}
}
But that would be cheating ;-)
If they are never referenced, make the classes default scope, so no other types outside of the package can see them. If they can't see them they can't reference them (without using reflection that is).
class Dummy {
//no-op
}
Why don't you just not put that class into the jar that gets deployed. That way it'll be there at compile time but if someone tried to access it at runtime you'll get a ClassNotFoundException.
Use AssertionError instead of IllegalStateException
I don't think you can do that, though you can put a #deprecated tag before the class declaration. This way the compiler will give you a warning if you try to use it, but it will still compile.
You could use your own ClassLoader and check every class against a black list of classes.
What do you mean by "use"? If you need to have them in there, it sounds like the compiler needs to be able to create the classes. However, if you don't want any instances of the class to be created, then create an Assertion or throw an exception in the actual constructor.

Categories

Resources