Conditional classes for j2me and j2se

D

David N. Welton

Hello,

I have the distinct suspicion this is a FAQ, however I'm not sure what
terms to search on.

The problem: I want to have a class - let's call it HttpRequest.
However, the low level details differ in the implementation of the code
behind the class for j2me and j2se. I would like to be able to have
other code that calls a method in HttpRequest and doesn't care what is
underneath, and therefore "runs everywhere".

It seems that standard Java offers a number of fancy techniques to do
the above. Even j2me apparently lets you do stuff like this:

c = Class.forName("javax.microedition.io.HttpConnection");

However, ideally it would be nice to do everything at compile time, so
as to save space in the j2me version of the code, as well as just
keeping things simpler.

Is it possible to do so without resorting to some sort of macro system?

Thankyou,
--
David N. Welton
- http://www.dedasys.com/davidw/

Apache, Linux, Tcl Consulting
- http://www.dedasys.com/
 
D

David N. Welton

David said:
Hello,

I have the distinct suspicion this is a FAQ, however I'm not sure what
terms to search on.

The problem: I want to have a class - let's call it HttpRequest.
However, the low level details differ in the implementation of the code
behind the class for j2me and j2se. I would like to be able to have
other code that calls a method in HttpRequest and doesn't care what is
underneath, and therefore "runs everywhere".

It seems that standard Java offers a number of fancy techniques to do
the above. Even j2me apparently lets you do stuff like this:

c = Class.forName("javax.microedition.io.HttpConnection");

However, ideally it would be nice to do everything at compile time, so
as to save space in the j2me version of the code, as well as just
keeping things simpler.

Is it possible to do so without resorting to some sort of macro system?

I found an answer I'm happy with:

Each directory has something like the following, which returns an
instance of the code that I want, and is compiled in.

public class HttpInstance {
public static HttpRequestClass getInstance() {
return new HttpRequestMicro();
}
}

Still a waste of space in that it's an extra class I don't need, but...
c'est la vie, I guess.

--
David N. Welton
- http://www.dedasys.com/davidw/

Linux, Open Source Consulting
- http://www.dedasys.com/
 
S

Sebastian Scheid

David N. Welton said:
The problem: I want to have a class - let's call it HttpRequest.
However, the low level details differ in the implementation of the code
behind the class for j2me and j2se. I would like to be able to have
other code that calls a method in HttpRequest and doesn't care what is
underneath, and therefore "runs everywhere".

That is the idea of polymorphism. Client code knows and uses only the
interface (e.g. HttpRequest) of an object. The concrete implementation of
the object is determined at runtime. The crucial point is how to obtain an
instance of the concrete object. This task can be taken by some kind of
factory for example and should not be done in the client.

It seems that standard Java offers a number of fancy techniques to do
the above. Even j2me apparently lets you do stuff like this:

c = Class.forName("javax.microedition.io.HttpConnection");

However, ideally it would be nice to do everything at compile time, so
as to save space in the j2me version of the code, as well as just
keeping things simpler.

If all the concrete implementations are known at compile time you don't need
reflection (Class.forName()). Your factory would look like

class HttpRequestFactory {
public HttpRequest createRequest() {
if (weAreRunningOnACellphone)
return new J2MEHttpRequest();
else
return new J2SEHttpRequest();
}
}

If this is the only place where you refer to J2SEHttpRequest and you run the
code on a cellphone you should be able to remove J2SEHttpRequest from the
classpath and save some space. If for some reason you reach the else branch
on a cellphone you will get a ClassDefNotFoundException.

Regards
Sebastian

P.S.: this is not the original gof factory pattern which lets a subclass of
the factory decide which concrete type is returned by create*().
 
D

David N. Welton

Sebastian said:
If all the concrete implementations are known at compile time you don't need
reflection (Class.forName()). Your factory would look like

class HttpRequestFactory {
public HttpRequest createRequest() {
if (weAreRunningOnACellphone)
return new J2MEHttpRequest();
else
return new J2SEHttpRequest();
}
}
If this is the only place where you refer to J2SEHttpRequest and you run the
code on a cellphone you should be able to remove J2SEHttpRequest from the
classpath and save some space. If for some reason you reach the else branch
on a cellphone you will get a ClassDefNotFoundException.

I ended up realizing that I could just do the obvious thing and have two
classes/files with the same name in different directories and compile
them in as needed. Duh! Your solution is elegant as well though and I
will keep it in mind as I will probably face more problems like this.

Thankyou,
--
David N. Welton
- http://www.dedasys.com/davidw/

Linux, Open Source Consulting
- http://www.dedasys.com/
 
R

Roedy Green

Is it possible to do so without resorting to some sort of macro system?

Java has no compile time facilities per se, though some constants are
evaluated at compile time.

Consider code like this:

// DoSomething is an abstract class or interface

static DoSomething doSomething;

static
{
if ( DEBUGGING )
{
doSomething = new DebugDoSomething();
}
else
{
doSomething = new ProductionDoSomething();
}
}

If DEBUGGING is a static final boolean known at compile time, only the
code for one branch of the if will be generated.
 
R

Roedy Green

I ended up realizing that I could just do the obvious thing and have two
classes/files with the same name in different directories and compile
them in as needed. Duh! Your solution is elegant as well though and I
will keep it in mind as I will probably face more problems like this.

If you go this mildly dangerous route, make sure each class brings
with it some sort of id that can be enumerated in an About Box so you
can tell for sure exactly what you have in a given jar.

You also better remember to delete class files before compiling or the
compiler might thing the class file from the other source version was
ok.
 
R

Roedy Green

public class HttpInstance {
public static HttpRequestClass getInstance() {
return new HttpRequestMicro();
}

You will not be happy with this. I know from experience. What you
can do, which generates the same code, is use a single global static
final boolean to control which version to use. Then you have only one
boolean to change and the compiler takes it from there. Best do a
clean compile after a boolean change.

You are right it is nice to avoid dynamic class loading. It is too
easy to leave a rarely used dynamically loaded class out of the jar
and not find out until it is an embarrassment. Dynamic class loading
also suppresses AOT optimisation.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,234
Members
46,821
Latest member
AleidaSchi

Latest Threads

Top