Is it possible to load one of two different classes in Java with the same name?

I have a lot of code that calls static methods on Foo, for example, "Foo.method ()". I have two different implementations of Foo and would like to use one or the other depending on the circumstances. In psuedocode:

File Foo1.java

class Foo1 implements Foo {
  public static int method() {
    return 0;
  }
} 

File Foo2.java

class Foo2 implements Foo {
  public static int method() {
    return 1;
  }
}

Main.java file

if(shouldLoadFoo1()) {
  Foo = loadClass("Foo1");
} else {
  Foo = loadClass("Foo2");
}

Is this possible with Java metaprogramming? I can't completely fool all documentation on loading a dynamic class. If not, what is the best way to do what I'm trying to do?

+3
source share
6 answers

Essentially, you have two classes with the same interface, but with different implementations. Wouldn't it be better to do this using an interface?

, , .

FooInterface foo;
MainClass (FooInteface foo, other fields) {
   this.foo = foo;
}


....

foo .

- AspectJ, , Foo.method, if (shouldLoadFoo1()) { Foo1.method()} ..

+3

factory.

static Foo makeMeAFoo()
{
  final Foo foo;
  if(shouldLoadFoo1()) {
    foo = new Foo1();
  } else {
    foo = new Foo2();
  }
  return foo;
}

, . hhafez '.

( , OBE b/c, , . ... , - kludge.)

+2

, , . Foo - , LHS . Java... .

, , , :

Class fooClass;
if (loadFoo1) {
    fooClass = Class.forName("some.pkg.Foo1");
} else {
    fooClass = Class.forName("some.pkg.Foo2");
}
Foo foo = (Foo) fooClass.newInstance();  // using the no-args constructor

( ...)

, fooClass Class, , . . , "" ... .


HOWEVER... , . , , , , , factory; . @andersoj.


UPDATE

, , , . (.. Foo1.method() Foo2.method()) , .

, , , Java:

  • .
  • .
  • Java. .

- , ; .

Class fooClass;

// Load one or other of the classes as above.

Method m = fooClass.getDeclaredMethod("method");
Integer res = (Integer) m.invoke(null);

( , )

, . , :

public static int method() {
    return useFoo1 ? Foo1.method() : Foo2.method();
}

OO: method Foo , Foo1 Foo2 .

, , method()... Foo1.method Foo2.method .

+2

, , .

singleton, .. :

public abstract class Foo {
    protected abstract void doSomeMethod();

    // populated at startup using whatever logic you desire
    public static Foo instance; 

    public static void someMethod() {
        instance.doSomeMethod();
    }
}

- - , , .. , . 4 jar:

  • loader.jar, . loader.jar Foo.
  • foo1.jar, Foo
  • foo2.jar, Foo
  • common.jar,

Loader.jar , :

void bootstrap() {
    URL commonUrl = // path to common.jar
    URL fooUrl;
    if (shouldUseFoo1()) {
        fooUrl = // path to Foo1.jar
    } else {
        fooUrl = // path fo Foo2.jar
    }
    URL[] urls = {fooUrl, commonUrl};
    ClassLoader loader = new UrlClassLoader(urls);
    Class<?> mainClass = loader.loadClass("my.main");
    mainClass.newInstance(); // start the app by invoking a constructor
}
+2

, ( , ), . (), , , .

private static int getResultOfFoo(Foo foo)
{
int res = -1;
if(foo instanceof Foo1)
    res = Foo1.method();
else res = Foo2.method();
return res;
}

: ", . , , , Java".

+2

Foo, Foo, . ( .)

, . , , , ( , ).

Sometimes it is wise to have different versions of a class (with the same external interface) for different configurations where it will be used (for example, “client-side” / “server-side”, when some common class in both modules depends on it), and in rare cases, you will have both modules in the same virtual machine at the same time, but in most cases it is better to use the “one interface and several implementing classes” approach.

+1
source

Source: https://habr.com/ru/post/1792115/


All Articles