I have a Java class Model which models some data from my remote database. I want all data models in my project to be able to supply a builder from a Map<String, Object> instance (in practice, I'm working with SnapshotParser<Model> parsers with Firestore, but I'll just call getData() in every model). This should look something like:
public class Model {
private String name;
public Model(String name) { this.name = name; }
public static SnapshotParser<Model> getDocParser() {
return docSnapshot -> {
Map<String, Object> data = docSnapshot.getData();
return new Model(data.getOrDefault("name", "John Doe"));
};
}
}
Note that I'll have several models (Model2, Model3...) which will also be required to provide such an interface. To enforce this behavior, I created a DocParserSupplier generic class for my model classes to implement:
public interface DocParserSupplier<T> {
static SnapshotParser<T> getDocParser();
}
This doesn't work for two reasons (as Android Studio informs me):
static methods of interfaces must have a default implementation. I can't do that without knowing T.
I get the "T cannot be referenced in static context" error.
If remove the static keyword from the above interface, I can do what I want but it would require I create an actual instance of the Model to get the parser. It would work but it makes more sense if the method is static.
Is there a Java way to do what I want?
EDIT: My specific use case is in matching RecyclerViews to documents in my database. Constructing the FirestoreRecyclerOptions object requires a parser to convert key-value data to a Model:
FirestoreRecyclerOptions<Model1> fro1 = new FirestoreRecyclerOptions.Builder<Model1>()
.setQuery(query1, Model1.getDocParser())
.build();
FirestoreRecyclerOptions<Model2> fro2 = new FirestoreRecyclerOptions.Builder<Model2>()
.setQuery(query2, Model2.getDocParser())
.build();
Interfaces enforce behavior of instances, so that references to any object which has that behavior can be passed around in a type-safe way. Static methods on the other hand, don't belong to any particular instance of an object; the class name is essentially just a namespace. If you want to enforce behavior, you will have to create an instance somewhere (or use reflection, if it is absolutely necessary to ensure a class has a particular static method).
Unless this system is going to be opened up for extension, where others can define their own models, I would say ditch the DocParserSupplier interface altogether and call the static methods exactly as you are now, or factor them out into a factory interface + implementation. The factory option is nice because you can replace the production implementation with a fake implementation that returns dummy parsers for tests.
Edit: Doc Parser Factory
public interface DocParserFactory {
SnapshotParser<Model1> getModel1Parser();
SnapshotParser<Model2> getModel2Parser();
...
SnapshotParser<Model1> getModelNParser();
}
...
// The implementation of each getModelXParser method
class DocParserFactoryImpl {
SnapshotParser<Model1> getModel1Parser() {
return docSnapshot -> {
Map<String, Object> data = docSnapshot.getData();
return new Model(data.getOrDefault("name", "John Doe"))};
}
...
}
...
private DocParserFactory docParserFactory;
// You can inject either the real instance (DocParserFactoryImpl) or a
// test instance which returns dummy parsers with predicable results
// when you construct this object.
public ThisObject(DocParserFactory docParserFactory) {
this.docParserFactory = docParserFactory;
}
...
// Your code
public void someMethod() {
...
FirestoreRecyclerOptions<Model1> fro1 = new
FirestoreRecyclerOptions.Builder<Model1>()
.setQuery(query1, docParserFactory.getModel1Parser())
.build();
FirestoreRecyclerOptions<Model2> fro2 = new
FirestoreRecyclerOptions.Builder<Model2>()
.setQuery(query2, docParserFactory.getModel2Parser())
.build();
...
}
It's not so much to do with static or non-static, as it is with the fact that you cannot create an instance of a generic object without passing the type parameter(s) one way or another. In fact, I answered a similar question a few days ago, when somebody wanted to use enums to get the required builder.
In short, you cannot write a method <T extends AbstractBuilder> T builder(final SomeNonGenericObject object) (or, in this case, <T extends AbstractBuilder> T builder()) without passing T in some form. Even though it will make sense at runtime, the compiler can't figure out what generic type to use if you don't tell it which one it is.
In Java 8, you can solve this elegantly with method references. I don't know much about Android, but I believe you're still on Java 6 there, so this wouldn't work.
Anyway, you can have something like the following:
public <T extends AbstractBuilder> T builder(final Supplier<T> object) {
return supplier.get();
}
final Supplier<AbstractBuilder> model1BuilderSupplier = Model1Builder::new;
builder(model1BuilerSupplier)
.setQuery(query1, Model1.getDocParser())
.build();
It's not exactly what you want, but the way you're trying to go about it will not work.
Related
I would like to write a generic algorithm, which can be instantiated with different objects. The objects are coming from 3rdparty and they have no common base class. In C++, I just write the generic algorithm as a template which takes the particular object as its argument. How to do it in Java?
template <class T>
class Algorithm
{
void Run(T& worker)
{
...
auto value = workder.DoSomething(someArgs);
...
}
};
In C++, I don't need to know anything about the T, because the proper types and availability of methods are checked during compilation. As far as I know,
in Java I must have a common base class for all my workers to be able to call methods on them. Is it right? Is there a way how to do similar stuff in Java?
I can't change my 3rdparty workers, and I don't want to make my own abstraction of all workers (including all types which the workers are using, etc.).
Edit:
Since I want to write the generic algorithm only once, maybe it could be a job for some templating language which is able to generate Java code (the arguments to the code template would be the workers)?
My solution:
In my situation, where I cannot change the 3rdparty workers, I have chosen Java code generation. I have exactly the same algorithm, I only need to support different workers which all provides identical interface (classes with same names, same names of methods, etc.). And in few cases, I have to do a small extra code for particular workers.
To make it more clear, my "workers" are in fact access layers to a proprietary DB, each worker for a single DB version (and they are generated).
My current plan is to use something like FreeMaker to generate multiple Java source files, one for each DB version, which will have only different imports.
The topic to look into for you: generics
You can declare a class like
public class Whatever<T> {
which uses a T that allows for any reference type. You don't need to further "specialize" that T mandatorily. But of course: in this case you can only call methods from Object on instances of T.
If you want to call a more specific method, then there is no other way but somehow describing that specification. So in your case, the reasonable approach would be to introduce at least some core interfaces.
In other words: there is no "duck typing" in Java. You can't describe an object by only saying it has this or that method. You always need a type - and that must be either a class or an interface.
Duck typing isn't supported in Java. It can be approximated but you won't get the convenience or power you're used to in C++.
As options, consider:
Full-on reflection + working with Object - syntax will be terrible and the compiler won't help you with compilation checks.
Support a pre-known set of types and use some sort of static dispatching, e.g a big switch / if-else-if block, a type -> code map, etc. New types will force changing this code.
Code generation done during annotation processing - you may be able to automate the above static-dispatch approach, or be able to create a wrapper type to each supported type that does implement a common interface. The types need to be known during compilation, new types require recompilation.
EDIT - resources for code generation and annotation processing:
Annotation processing tutorial by #sockeqwe
JavaPoet, a clean code generation tool by Square
If you really don't have any way to get it done correctly with generics you may need to use reflection.
class A {
public String doIt() {
return "Done it!";
}
}
class B {
public Date doIt() {
return Calendar.getInstance().getTime();
}
}
interface I {
public Object doIt();
}
class IAdapter implements I {
private final Object it;
public IAdapter(Object it) {
this.it = it;
}
#Override
public Object doIt() {
// What class it it.
Class<?> itsClass = it.getClass();
// Peek at it's methods.
for (Method m : itsClass.getMethods()) {
// Correct method name.
if (m.getName().equals("doIt")) {
// Expose the method.
m.setAccessible(true);
try {
// Call it.
return m.invoke(it);
} catch (Exception e) {
throw new RuntimeException("`doIt` method invocation failed", e);
}
}
}
// No method of that name found.
throw new RuntimeException("Object does not have a `doIt` method");
}
}
public void test() throws Exception {
System.out.println("Hello world!");
Object a = new IAdapter(new A()).doIt();
Object b = new IAdapter(new B()).doIt();
System.out.println("a = "+a+" b = "+b);
}
You should, however, make every effort to solve this issue using normal type-safe Java such as Generics before using reflection.
In Java all your Workers must have a method DoSomething(someArgs), which doesn't necessarily imply that they extend the same base class, they could instead implement an interface Worker with such a method. For instance:
public interface Worker {
public Double DoSomething(String arg1, String arg2);
}
and then have different classes implement the Worker interface:
One implementation of Worker:
public class WorkerImplA implements Worker{
#Override
public Double DoSomething(String arg1, String arg2) {
return null; // do something and return meaningful outcome
}
}
Another implementatin of Worker:
public class WorkerImplB implements Worker{
#Override
public Double DoSomething(String arg1, String arg2) {
return null; // do something and return meaningful outcome
}
}
The different WorkerImpl classes do not need to extend the same common base class with this approach, and as of JavaSE 8 interfaces can have a default implementation in any method they define.
Using this approach Algorithm class would look like:
public class Algorithm {
private String arg1;
private String arg2;
public Algorithm(String arg1, String arg2){
this.arg1 = arg1;
this.arg2 = arg2;
}
public void Run(Worker worker){
worker.DoSomething(arg1, arg2);
}
}
I've the case that I have four types of data objects:
class DataTypeAlpha extends DataType
class DataTypeBeta extends DataType
class DataTypeGamma extends DataType
class DataTypeDelta extends DataType
and four different TreeNode types from the GUI framework, each one specific to the wrapped DataType:
class AlphaTreeNode extends MyAppTreeNode
...
Now I often have the pattern that I have an instance of DataType and need a new instance of MyAppTreeNode. I see two solutions. Solution one:
class DataType {
// Instantiates and returns the appropriate MyAppTreeNode for this DataType
abstract MyAppTreeNode createTreeNode();
}
Solution two:
class MyAppTreeNode {
static MyAppTreeNode createTreeNodeForDataType(DataType dataType) {
if(dataType instanceOf DataTypeAlpha) return new AlphaTreeNode((DataTypeAlpha)dataType)
else if (dataType instanceOf DataTypeBety) return new BetaTreeNode((DataTypeBeta)dataType)
else if ...
else if ...
else throw new IllegalArgumentException();
}
}
Solution one uses polymorphism, is shorter and more "elegant". But I'd prefer that the DataType classes have no knowledge about the GUI framework that I use. Maybe I could even use two different GUI frameworks?
Do you see a third solution? I added the Guice tag to this question. Maybe there is some function in Guice or another dependency injection library that could help here?
Looking through similar questions:
Of course I will use the Factory Pattern for this, but inside the factory I'm still left with the question.
You might use a visitor inspired approach for this. As usual all DataType objects has an accept method, but as opposed to the normal visitor pattern, it does not traverse children and it will return a value. To avoid too much confusion, lets call object passed to accept for an operator instead of visitor. The trick is to make accept and operators return a generic type.
So the code will be something like this in the data model
public abstract class DataType {
public abstract <T> T accept(Operator<T> op);
}
public interface Operator<T> {
T operateAlpha(DataTypeAlpha data);
T operateBeta(DataTypeBeta data);
...
}
public class DataTypeAlpha extends DataType {
public <T> T accept(Operator<T> op) {
return op.operateAlpha(this);
}
}
....
and in the GUI you will have
public class TreeNodeFactory implements Operator<MyAppTreeNode> {
public MyAppTreeNode operateAlpha(DataTypeAlpha data) {
return new AlphaTreeNode(data);
}
...
}
public class MyAppTreeNode {
static TreeNodeFactory factory = ...;
static MyAppTreeNode createTreeNodeForDataType(DataType dataType) {
return dataType.accept(factory);
}
}
So the short, simple answer is that a constructor can only return its own type. No subtypes, no other classes, no reused instances, no null—only a new instance of that type. So you're looking for a solution that operates outside the confines of a constructor here. The simplest and most common workaround is to write a static factory method (usually named newInstance or getInstance) which returns any new or existing instance of the enclosing class and can return a subclass or null without trouble.
Your points about your solution 1 and 2 are valid. It'd be great to avoid making the data types aware of the UI, and in your situation (with only four types) I'd probably opt for your solution 2. If you have operations that will vary among those types—which is a pretty common requirement in a GUI that puts a mixture of types into a tree—Bittenus's solution is probably worth it. (It's a lot of code to handle if you only need to do this sort of thing once.)
If you somehow expect your type count to grow but your operations to never grow, one alternative is to extract the polymorphic creation into a separate Factory, which might look like this:
class MyAppTreeNode {
interface Factory {
MyAppTreeNode create(DataType type);
}
}
class AlphaTreeNode extends MyAppTreeNode {
static class Factory implements MyAppTreeNode.Factory {
#Override public AlphaTreeNode create(DataType type) {
// Remember, in an override your return types can be more-specific
// but your parameter types can only be less-specific
return new AlphaTreeNode((DataTypeAlpha) type);
}
}
}
Then you can just make a map (though consider Guava's ImmutableMap for better semantics):
private static Map<Class<?>, MyAppTreeNode.Factory> factoryMap = new HashMap<>();
static {
factoryMap.put(DataTypeAlpha.class, new AlphaTreeNode.Factory());
// ...
}
public static createTreeNode(DataType type) {
return factoryMap.get(type.getClass()).create(type);
}
More trouble than it's worth? Probably, in most cases. But bear in mind that it's probably the best that Guice can get you, as well. Guice has some ability to auto-generate the Factory implementation for you, but you'll still need to map DataType to MyAppTreeNode.Factory one way or another, and it's going to have to live in a Map, a conditional, or the double indirection that powers the Visitor pattern.
Hope this helps, if only to endorse the answers you already have!
I am working on a java application. The is an abstract class Model and 2 derived classes Model 1 and Model 2. Model1 and Model2 behave differently, so I want to allow the user to select a model from the two.
It can be implemented like:
Model model;
If(response==1){
model = new Model1();
}else if(response==2){
model = new Model2();
}
Now the problem with this is, that if I add a new class Model3, I have to rewrite the code.
I could create a List, where I would add an instance from each class, then I would add a static method, that would return a new Instance of the class, but I hope it can be done with bit a more style.
Is there possible to create a List, to hold the type of each class. From this List I could create a menu to select a model, and then use the type to create the class the user needs.
So is it possible, to create a List<Class>, then use the Class object as a constructor, to create an instance of the given class?
You can create a list of suppliers:
static final List<Supplier<Model>> MODEL_MAKERS = ImmutableList.of(
new Supplier<Model>() { public Model get() { return new Model1(); } },
new Supplier<Model>() { public Model get() { return new Model2(); } },
new Supplier<Model>() { public Model get() { return new Model3(); } }
);
You could muck around with reflection, but that requires stepping outside Java's normal exception handling mechanisms, requires zero-argument public constructors and public classes which limits how code can change under maintenance in ways that aren't checked by javac, and just isn't necessary in this case.
If you are sure that it will have a public no-args constructor, you can use Class.newInstance()
For more complicated uses, you can find a Constructor object with Class.getConstructor(s) and then invoke it that way.
Once you have that, it is relatively easy to stick your Classes into a Map or something to do lookups and create instances.
Yes, you can use the newInstance() method on Class to construct one. It has to have a no-args constructor though.
There is a part in my java code where I am extending a class from a library which I haven't written.
#override
public Object getPropertyValue(Object id) {
if(id.equals(model.PROPERTY_RENAME))
model.setName((String)value);
else if(id.equals(model.PROPERTY_COLOUR))
model.setColor((Color)value);
}
Now in this case how should I modify this code to make it scalable. There would be many more properties like location, dimension, etc. Now this model is instance of an abstract class AbsModel.
So every class implementing the AbsModel would have different properties. So the class architecture should be there, so that this part of code remains unchanged, no matter how many more model classes I add.
It looks like you want to carry out some operation on the model when this method (getPropertyValue) is called. I would create a Map of id onto the interface ModelOperation defined as follows:
public interface ModelOperation {
void operate(Object value);
}
Then the map would be defines as follows:
map.put(model.PROPERTY_RENAME, new RenameOperation(model));
Your extension class would then look like this:
#Override
public Object getPropertyValue(Object id) {
map.get(id).operate(model);
// etc...
}
For example, RenameOperation would be defined like this:
public class RenameOperation implements ModelOperation {
public RenameOperation(Model model) {
// etc...
}
public void operate(Object value) {
model.setName((String)value);
}
}
This allows you to support as many model operations as you like and means you don't have to change the extension class you have to write. The above is just an outline. You could use generics on the ModelOperation implementations to avoid the cast of the value in each one.
I guess reflection is probably the answer here if you can rely on some naming to help direct you.
It's not going to be nice, but the idea would be that you'd have a method that would reflect on the type and look up the appropriate method. The code belwo
public Object setPropertyValue(Object id) {
String className = id.getClass().getSimpleName();
// Hope that the method is called set<CLASS> and takes a single parameter that is the class
Method method = model.class.getMethod("set" + className, id.getClass());
// Invoke the method (TODO deal with all of the exceptions)
method.invoke(model, id);
}
There are multiple ways of doing this -- though it depends on what do you mean by "scalable" (being able to cope with lots of requests per second or being able to cope with lots of properties?):
one way -- if you're going to go down the path you have outlined in your code is to have those properties that are used very often at the top of your if/then/else block -- so their execution path is very short. this would "scale up" well for lots of requests as not too much time is being spent in actually executing the method (in most cases at least!)
another way -- and this scales up well for lots of properties and easiness of maintaining the code but you will take a hit on execution time: have a Map that maps property names to setxxx() method names, then you can use reflection to invoke these methods on the target object (id in your case) on each call. Classes extended your class will only have to provide a getMap() method which will return the mapping name-to-setter method, which can be a static member and initialized on class load.
Store your properties in a Map -- in which case setName() is the same as map.put( PROPERTY_RENAME, value)
Since in Java functions are not first class citizens, the "nice" route would be very awkward: define an enum with one value per each constant above (i.e. for each property), and a virtual method e.g. update(Object value, then override the method in each enum to update the corresponding property. If you can, redefine the constants PROPERTY_RENAME etc. themselves as enums. This still results in code bloat.
The other way is to use reflection. If you can use the same ids as the property names you want to update, you only need to invoke the setter for the property (as illustrated in other answers). Otherwise you may need to introduce a mapping from ids to property names.
A version not using reflection, call the base class's implementation:
public Object getValue(Object id) {
Object ret = super.getValue(id);
if (ret == null) {
// Subclass specific properties
}
return ret;
}
A common way around this is to use reflection like
public Object getValue(IdType id) {
Method getter = model.getClass().getMethod("get" + id);
return getter.invoke(model); // throws Exceptions.
}
OR
public void setValue(IdType id, Object value) {
Method setter = model.getClass().getMethod("set" + id, value.getClass());
setter.invoke(model, value); // throws Exceptions.
}
I solved this issue by creating an interface. So the code is.
public interface IModel
{
public void setProperty(String propertyName);
}
Rest of the classes were
public class HelloModel implements IModel
{
public void setProperty(String propertyName)
{ code for handling the properties goes here ... }
}
So in this case every class has to handle it's own property setters.
Is this the best way to handle abstraction ? I think this model is very scalable ...
Introduction
As a disclaimer, I'v read Why can't static methods be abstract in Java and, even if I respectfully disagree with the accepted answer about a "logical contradiction", I don't want any answer about the usefulness of static abstract just an answer to my question ;)
I have a class hierarchy representing some tables from a database. Each class inherits the Entity class which contains a lot of utility methods for accessing the database, creating queries, escaping characters, etc.
Each instance of a class is a row from the database.
The problem
Now, in order to factorize as much code as possible, I want to add information about related columns and table name for each class. These informations must be accessible without a class instance and will be used in Entity to build queries among other things.
The obvious way to store these data are static fields returned by static methods in each class. Problem is you can't force the class to implement these static methods and you can't do dynamic linking on static methods call in Java.
My Solutions
Use a HashMap, or any similar data structure, to hold the informations. Problem : if informations are missing error will be at runtime not compile time.
Use a parallel class hierarchy for the utility function where each corresponding class can be instantiated and dynamic linking used. Problem : code heavy, runtime error if the class don't exist
The question
How will you cope with the absence of abstract static and dynamic linking on abstract method ?
In a perfect world, the given solution should generate a compile error if the informations for a class are missing and data should be easily accessible from withing the Entity class.
The answer doesn't need to be in Java, C# is also ok and any insight on how to do this without some specific code in any language will be welcomed.
Just to be clear, I don't have any requirement at all besides simplicity. Nothing have to be static. I only want to retrieve table and columns name from Entity to build a query.
Some code
class Entity {
public static function afunction(Class clazz) { // this parameter is an option
// here I need to have access to table name of any children of Entity
}
}
class A extends Entity {
static String table = "a";
}
class B extends Entity {
static String table = "b";
}
You should use the Java annotation coupled with the javac annotation processor, as it's the most efficient solution. It's however a bit more complicated than the usual annotation paradigm.
This link shows you how you can implement an annotation processor that will be used at the compile time.
If I reuse your example, I'd go this way:
#Target(ElementType.TYPE)
#Retention(RetentionType.SOURCE)
#interface MetaData {
String table();
}
abstract class Entity {}
#MetaData(table="a")
class A extends Entity {}
#MetaData(table="b")
class B extends Entity {}
class EntityGetter {
public <E extends Entity> E getEntity(Class<E> type) {
MetaData metaData = type.getAnnotation(MetaData.class);
if (metaData == null) {
throw new Error("Should have been compiled with the preprocessor.");
// Yes, do throw an Error. It's a compile-time error, not a simple exceptional condition.
}
String table = metaData.table();
// do whatever you need.
}
}
In your annotation processing, you then should check whether the annotation is set, whether the values are correct, and make the compilation fail.
The complete documentation is available in the documentation for the package javax.annotation.processing.
Also, a few tutorials are available on the Internet if you search for "java annotation processing".
I will not go deeper in the subject as I never used the technology myself before.
I have run into the same problems as you, and am using the following approach now. Store Metadata about columns as annotations and parse them at runtime. Store this information in a map. If you really want compile time errors to appear, most IDEs (Eclipse e.g.) support custom builder types, that can validate the classes during build time.
You could also use the compile time annotation processing tool which comes with java, which can also be integrated into the IDE builds. Read into it and give it a try.
In Java the most similar approach to "static classes" are the static enums.
The enum elements are handed as static constants, so they can be accesed from any static context.
The enum can define one or more private constructors, accepting some intialization parameters (as it could be a table name, a set of columns, etc).
The enum class can define abstract methods, which must be implemented by the concrete elements, in order to compile.
public enum EntityMetadata {
TABLE_A("TableA", new String[]{"ID", "DESC"}) {
#Override
public void doSomethingWeirdAndExclusive() {
Logger.getLogger(getTableName()).info("I'm positively TableA Metadata");
}
},
TABLE_B("TableB", new String[]{"ID", "AMOUNT", "CURRENCY"}) {
#Override
public void doSomethingWeirdAndExclusive() {
Logger.getLogger(getTableName()).info("FOO BAR message, or whatever");
}
};
private String tableName;
private String[] columnNames;
private EntityMetadata(String aTableName, String[] someColumnNames) {
tableName=aTableName;
columnNames=someColumnNames;
}
public String getTableName() {
return tableName;
}
public String[] getColumnNames() {
return columnNames;
}
public abstract void doSomethingWeirdAndExclusive();
}
Then to access a concrete entity metadata this would be enough:
EntityMetadata.TABLE_B.doSomethingWeirdAndExclusive();
You could also reference them from an Entity implemetation, forcing each to refer an EntityMetadata element:
abstract class Entity {
public abstract EntityMetadata getMetadata();
}
class A extends Entity {
public EntityMetadata getMetadata() {
return EntityMetadata.TABLE_A;
}
}
class B extends Entity {
public EntityMetadata getMetadata() {
return EntityMetadata.TABLE_B;
}
}
IMO, this approach will be fast and light-weight.
The dark side of it is that if your enum type needs to be really complex, with lot of different params, or a few different complex overriden methods, the source code for the enum can become a little messy.
Mi idea, is to skip the tables stuff, and relate to the "There are not abstract static methods". Use "pseudo-abstract-static" methods.
First define an exception that will ocurr when an abstract static method is executed:
public class StaticAbstractCallException extends Exception {
StaticAbstractCallException (String strMessage){
super(strMessage);
}
public String toString(){
return "StaticAbstractCallException";
}
} // class
An "abstract" method means it will be overriden in subclasses, so you may want to define a base class, with static methods that are suppouse to be "abstract".
abstract class MyDynamicDevice {
public static void start() {
throw new StaticAbstractCallException("MyDynamicDevice.start()");
}
public static void doSomething() {
throw new StaticAbstractCallException("MyDynamicDevice.doSomething()");
}
public static void finish() {
throw new StaticAbstractCallException("MyDynamicDevice.finish()");
}
// other "abstract" static methods
} // class
...
And finally, define the subclasses that override the "pseudo-abstract" methods.
class myPrinterBrandDevice extends MyDynamicDevice {
public static void start() {
// override MyStaticLibrary.start()
}
/*
// ops, we forgot to override this method !!!
public static void doSomething() {
// ...
}
*/
public static void finish() {
// override MyStaticLibrary.finish()
}
// other abstract static methods
} // class
When the static myStringLibrary doSomething is called, an exception will be generated.
I do know of a solution providing all you want, but it's a huge hack I wouldn't want in my own code nowadays:
If Entity may be abstract, simply add your methods providing the meta data to that base class and declare them abstract.
Otherwise create an interface, with methods providing all your data like this
public interface EntityMetaData{
public String getTableName();
...
}
All subclasses of Entity would have to implement this interface though.
Now your problem is to call these methods from your static utility method, since you don't have an instance there. So you need to create an instance. Using Class.newInstance() is not feasable, since you'd need a nullary constructor, and there might be expensive initialization or initialization with side-effects happening in the constructor, you don't want to trigger.
The hack I propose is to use Objenesis to instantiate your Class. This library allows instatiating any class, without calling the constructor. There's no need for a nullary constructor either. They do this with some huge hacks internally, which are adapted for all major JVMs.
So your code would look like this:
public static function afunction(Class clazz) {
Objenesis objenesis = new ObjenesisStd();
ObjectInstantiator instantiator = objenesis.getInstantiatorOf(clazz);
Entity entity = (Entity)instantiator.newInstance();
// use it
String tableName = entity.getTableName();
...
}
Obviously you should cache your instances using a Map<Class,Entity>, which reduces the runtime cost to practically nothing (a single lookup in your caching map).
I am using Objenesis in one project of my own, where it enabled me to create a beautiful, fluent API. That was such a big win for me, that I put up with this hack. So I can tell you, that it really works. I used my library in many environments with many different JVM versions.
But this is not good design! I advise against using such a hack, even if it works for now, it might stop in the next JVM. And then you'll have to pray for an update of Objenesis...
If I were you, I'd rethink my design leading to the whole requirement. Or give up compile time checking and use annotations.
Your requirement to have static method doesn't leave much space for clean solution. One of the possible ways is to mix static and dynamic, and lose some CPU for a price of saving on RAM:
class Entity {
private static final ConcurrentMap<Class, EntityMetadata> metadataMap = new ...;
Entity(EntityMetadata entityMetadata) {
metadataMap.putIfAbsent(getClass(), entityMetadata);
}
public static EntityMetadata getMetadata(Class clazz) {
return metadataMap.get(clazz);
}
}
The way I would like more would be to waste a reference but have it dynamic:
class Entity {
protected final EntityMetadata entityMetadata;
public Entity(EntityMetadata entityMetadata) {
this.entityMetadata=entityMetadata;
}
}
class A extends Entity {
static {
MetadataFactory.setMetadataFor(A.class, ...);
}
public A() {
super(MetadataFactory.getMetadataFor(A.class));
}
}
class MetadataFactory {
public static EntityMetadata getMetadataFor(Class clazz) {
return ...;
}
public static void setMetadataFor(Class clazz, EntityMetadata metadata) {
...;
}
}
You could get even get rid of EntityMetadata in Entity completely and leave it factory only. Yes, it would not force to provide it for each class in compile-time, but you can easily enforce that in the runtime. Compile-time errors are great but they aren't holy cows after all as you'd always get an error immediately if a class hasn't provided a relevant metadata part.
I would have abstracted away all meta data for the entities (table names, column names) to a service not known by the entities them selfs. Would be much cleaner than having that information inside the entities
MetaData md = metadataProvider.GetMetaData<T>();
String tableName = md.getTableName();
First, let me tell you I agree with you I would like to have a way to enforce static method to be present in classes.
As a solution you can "extend" compile time by using a custom ANT task that checks for the presence of such methods, and get error in compilation time. Of course it won't help you inside you IDE, but you can use a customizable static code analyzer like PMD and create a custom rule to check for the same thing.
And there you java compile (well, almost compile) and edit time error checking.
The dynamic linking emulation...well, this is harder. I'm not sure I understand what you mean. Can you write an example of what you expect to happen?