2

I am trying to load a class dynamically through reflection by using the method Class.forname("classname") as given in below code.

Class<? extends Layout> layoutClassName;
try {
    layoutClassName = (Class<? extends Layout>)   Class.forName(site.getSiteLayout());
} catch (ClassNotFoundException e) {
    layoutClassName= DefaultLayout.class;
}

I am trying to load a class dynamically if it is defined by the logged in user (db configuration), otherwise provide the default implementation.

This works fine, but after a statistical analysis we found that approximately 80% of the times default implementation is used.

This means approximately 80% of times an Exception object is created. Since creating exception objects is heavy, I would like to avoid it and use some other logic to Identify if a class is present or not.

Please suggest.

PS: I am not looking for any significant performance boost, I am just trying to clean up my existing code.

default locale
  • 13,035
  • 13
  • 56
  • 62
Mohit Kanwar
  • 2,962
  • 7
  • 39
  • 59
  • Try the forName(String name, boolean initialize, ClassLoader loader) method of Class and set the param initialize to false.http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#forName%28java.lang.String,%20boolean,%20java.lang.ClassLoader%29 – Jabir Aug 11 '15 at 07:15
  • `I am just trying to clean up my existing code.` Exception handling seems clean enough for me in this situation. I don't think it's possible to avoid `ClassNotFoundException` here without using ad-hoc methods (list of all layout classes, etc.) – default locale Aug 11 '15 at 07:21
  • @Jabir this method will also throw `ClassNotFoundException` – default locale Aug 11 '15 at 07:22
  • Ahh got it forgot about that part – Jabir Aug 11 '15 at 07:25
  • 1
    Just don't use reflection – michaelsnowden Aug 11 '15 at 07:27
  • @michaelsnowden Is there a better alternative? I want users to define the type of object to be instantiated. – Mohit Kanwar Aug 11 '15 at 07:29
  • @MohitKanwar Why do you want users to define the type of object to be instantiated? It seems like bad design to have your user's input coupled to the exact name of your Java classes. – michaelsnowden Aug 11 '15 at 07:34
  • okay, here is the scenario: I want my user (admin) to define layout of a website/widget which he controls. The user sees a list of available options, and selects one of them (optional field). The list of layouts is dynamic as the product can be customized and more layouts can be added once released into production. – Mohit Kanwar Aug 11 '15 at 07:38
  • The list of available options is mapped to a class, so directly there is no way that a user provides a wrong input or input to a malicious file/java class – Mohit Kanwar Aug 11 '15 at 07:41
  • 1
    If this is run only at startup or configuration time, just don't worry about it. Exception handling is fine here. – chrylis -cautiouslyoptimistic- Aug 11 '15 at 07:46

2 Answers2

1

As you said...

I am trying to load a class dynamically if it is defined in configuration

Is the 'configuration' is mentiond in some file.

I hope you can get hold of the configuration file(or the configuration status), and create the object for the class only and only if it is mentioned to do so. If not apply the default implementation.

If you cant access the configuration i fear there is no other way as far as i know.

Sidharth Dash
  • 333
  • 1
  • 4
  • 13
  • unfortunately that is not the case. Edited the question for more clarification. By configuration I mean user defined configuration, which is stored and fetched from db – Mohit Kanwar Aug 11 '15 at 07:34
  • 'By configuration I mean user defined configuration, which is stored and fetched from db' Cant you access the DB ?? I think the DB would be reachable by any of your program code. If so than it would be easy. – Sidharth Dash Aug 11 '15 at 08:32
1

I don't know if there's a convenient way to check if class exists without throwing ClassNotFoundException that will work for general case.

Handling ClassNotFoundException seems appropriate and clear in this situation. There are several earlier questions that all recommend to handle exception: 1, 2, 3

But if you really want to:

  • load layouts dynamically (so, you can't avoid reflection);
  • load layouts by unrestricted class name (if you don't have configuration, can't build defined and relatively stable list of all layout classes);
  • minimize ClassNotFoundException for some reason.

then I can suggest to cache layout classes. If you don't have a large number of different layouts something like this might work:

private HashMap<String, Class<? extends List>> layoutsByName  = new HashMap<>();

public Class<? extends Layout> getLayout(String name) {
    Class<? extends Layout> layoutClass = layoutsByName.get(name);
    if(layoutClass!=null) {
        return layoutClass;
    }
    layoutClass = getLayoutUsingReflection(name);
    layoutsByName.put(name, layoutClass);
    return layoutClass;
}

private Class<? extends Layout> getLayoutUsingReflection(String name) {
    try {
        return (Class<? extends Layout>) Class.forName(name);
    } catch (ClassNotFoundException e) {
        return DefaultLayout.class;
    }
}

This way you won't check for the same layout twice.

Community
  • 1
  • 1
default locale
  • 13,035
  • 13
  • 56
  • 62
  • 1
    And populating of this hashmap can be done once (or only when a new layout is added/existing is deleted). Looks a nice alternative. Thanks. – Mohit Kanwar Aug 11 '15 at 07:50