Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / March 2006

Tip: Looking for answers? Try searching our database.

How to achieve this?

Thread view: 
wensa - 05 Mar 2006 13:33 GMT
For the following code:

class A {}

class a1 extends A {}

class a2 extends A {}

...

class an extends A {}

Is there a method to store all the names of A's subclasses into a
String array dynamically,
such as

String a[] = findAllSubClassesofA();

Then a[] has the content of {"a1", "a2", ..., "an"}

How to write the method findAllSubClassesofA()?

Thanks in advance!
Roedy Green - 05 Mar 2006 15:18 GMT
>Is there a method to store all the names of A's subclasses into a
>String array dynamically,
If there is, it will be buried somewhere in the Java.lang.reflect
package.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Stefan Schulz - 05 Mar 2006 17:09 GMT
> String a[] = findAllSubClassesofA();
>
> Then a[] has the content of {"a1", "a2", ..., "an"}
>
> How to write the method findAllSubClassesofA()?

You can't really write it, since someone might just decide to call
ClassLoader#defineClass("An+1", ...); just after your
findAllSubClassesofA() returns.
Adam Maass - 05 Mar 2006 19:42 GMT
> For the following code:
>
[quoted text clipped - 17 lines]
>
> How to write the method findAllSubClassesofA()?

The short answer is that the reflection APIs do not provide a way to get the
subclasses of a given class. (Unlike the superclasses and superinterfaces of
a given class, the subclasses do not have to be loaded when a class is
loaded. So, at the time you make the query, the VM might not even be aware
of /any/ subclasses of A.)

You might want to hardcode the expected response in your
findAllSubClassesofA() method.

You could attempt to find (or recreate) the classpath that you're operating
on, and iterate over the .class files you find this way, querying each one
to see if it meets your requirements. (This is painful, though possible, to
do.) Be aware that this approach won't find subclasses of A that don't exist
on the classpath. (Ex, it is possible to dynamically generate at runtime a
subclass of A.) It presumes that there's a way to iterate over items on the
classpath -- this isn't always true. Even if it is true, it's quite slow and
hard to get right. (I've done something like it in the past.)
Owen Jacobson - 05 Mar 2006 21:12 GMT
> For the following code:
>
[quoted text clipped - 17 lines]
>
> How to write the method findAllSubClassesofA()?

If (and ONLY if) you control all subclasses of A, you can have them
register themselves with A when loaded:

class A {
 private static final Set<Class<? extends A>> subclasses = ...;

 protected static registerSubclass (Class<? extends A> clazz) {
   assert (clazz != null);
   subclasses.add (clazz);
 }

 public static Iterable<Class<? extends A>> getSubclasses () {
   return Collections.unmodifiableSet (subclasses);
 }
}

class A1 {
 static { // happens when A1 is loaded
   registerSubclass (A1.class);
 }
}

However, the results of A.getSubclasses () will be different at different
points in execution, as subclasses are loaded.

If you don't control derivation from A, this doesn't work, and nothing
else actually does.  You may want to stop wanting that and find another
solution to your problem.

-Owen
Owen Jacobson - 05 Mar 2006 21:19 GMT
Oops.

> class A1 {

class A1 extends A {

>   static { // happens when A1 is loaded
>     registerSubclass (A1.class);
>   }
> }

Owen
wensa - 06 Mar 2006 03:38 GMT
If, for each subclass, there is a static field or method, just like

class a1 extends A {
 static int ...
 static void callme() {}
}

Would it be loaded automatically when program launched?

> > For the following code:
> >
[quoted text clipped - 48 lines]
>
> -Owen
Owen Jacobson - 06 Mar 2006 03:44 GMT
> If, for each subclass, there is a static field or method, just like
>
[quoted text clipped - 4 lines]
>
> Would it be loaded automatically when program launched?

Not if those fields and methods are in the class you want loaded, no.  A
class is only loaded when referenced by something already loaded, and the
only[0] class loaded at startup is the class main(String[]) is defined on.

Owen

[0] broad, broad simplification
rukbate - 06 Mar 2006 04:29 GMT
I'm afraid not. Java VM uses some way called lazy load. Unless you
really need a class, the VM won't load it.
Patricia Shanahan - 05 Mar 2006 21:16 GMT
> For the following code:
>
[quoted text clipped - 19 lines]
>
> Thanks in advance!

As others have indicated, you can't do exactly what you want.

However, if you control class A, you can find all subclasses for which
at least one instance has been created.

Keep a static Set of subclass names. In A's constructor, check whether
the current object's class name is "A" (possibly qualified with package
name), or any String in the Set. If not, insert the name in the Set.
findAllSubClassesofA returns the Set's toArray() result.

All this stuff gets very awkward. Could you tell us what you are trying
to achieve at the next level up? Why do you want the array of subclass
names? There may be an easier solution to your real problem.

Patricia
wensa - 06 Mar 2006 03:32 GMT
My real problem is something that could be sovled by using Factory
pattern, In superclass A, there is a static method getA(String), like:
class A {
...
public static A getA(String ss) {...}
}
When I pass a string to getA(String), it should return the
corresponding subclass of A. e.g.
class a1 extends A {}
class a2 extends A {}
then getA("1") should return a1, getA("2") should return a2.

But, if I add some other subclasses such as
class a3 extends A {}
I should modify the code in getA(String) to get it work.

Is there some method to avoiding the modification?
rukbate - 06 Mar 2006 04:26 GMT
The eaist way for your purpose is to use a configuration file to
indicate which subclass you want, and read the file in the Factory
class.
Patricia Shanahan - 06 Mar 2006 05:44 GMT
> My real problem is something that could be sovled by using Factory
> pattern, In superclass A, there is a static method getA(String), like:
[quoted text clipped - 13 lines]
>
> Is there some method to avoiding the modification?

Does this solve your problem?

java.lang.Class has a static method forName. Use that to get the Class
object, if any, corresponding to "a"+ss. Use A's Class object's
isAssignableFrom to check that it is a subclass of A. If all is OK,
return the class you found. If not, throw an appropriate exception.

This should work as long as either you have a consistent system for
naming the subclasses, or the caller of getA knows the actual name of
the subclass.

Since you mention the Factory pattern, you may want to return an
instance of the subclass rather than its Class object. You can do that
using the Class newInstance method, or going into java.lang.reflect if
that does not handle you case.

However, the point of the Factory pattern is to shift the subclass
selection from the caller to the factory. Why does the caller need to
tell A which subclass to use, rather than giving A parameters describing
the caller's requirements and letting A pick a subclass?

Patricia


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.