Getting information about children

E

Eric

Hi all,

I've been trying to get my mind around a certain setup, and am sure I'm
missing something. I was hoping someone could shed some light on it.

Say you had a simple library type application, and you set it up so
that all books would be children of a Book superclass:

public class Book {}

public class Philosophy extends Book {
static int DeweyDecimal = 601;
}

public class JavaProgramming extends Book {
static int DeweyDecimal = 005;
}

public class WebstersDictionary extends Book {
static int DeweyDecimal = 903;
}

Now, if I had an array I'd created off all the classes of books (e.g.
Book[] books = {Philosophy.class, JavaProgramming.class,
WebstersDictionary.class}) how would I go about getting the
DeweyDecimal number of one of the types of books without instantiating
them?

I'd be happy to do so through a method, or add anything to the parent
class, but although I've looked at reflection and thought about it a
fair bit, I haven't been able to figure out a way to do this...

Any thoughts? :)

Eric
 
E

Eric

I'm currently using 1.4.2, but would grudgingly update if 1.5 provides
a clean solution to this.

Thanks,

Eric
 
R

Roedy Green

Now, if I had an array I'd created off all the classes of books (e.g.
Book[] books = {Philosophy.class, JavaProgramming.class,
WebstersDictionary.class}) how would I go about getting the
DeweyDecimal number of one of the types of books without instantiating
them?


You could use something like BCEL to analyse the class files and
extract the info, but that seems one heck of a lot of work.
see http://mindprod.com/jgloss/jasm.html
for the link to BCEL.

Another way entirely to get it is to write a little regex that chases
through the source code extracting the needed numbers.

You can get the numbers without instantiating, but with loading the
classes with code something like this:

int[] numbers = { Philosophy.deweyDecimal, Java.deweyDecimal ... };

If you make deweyDecimal a static final, I suspect that code might
even get them without loading the classes.

Do a Java -verbose to be sure.

If you defined an interface Dewey with an instance method called
getDeweyDecimal, and all your classes implement it, then you could say
something like this:


for ( String className : classNames )
{
Class dynamicallyLoadedClass = Class.forName( com.yourdomain.books."
+ className );
Dewey d = (Dewey)( dynamicallyLoadedClass.newInstance() );
int number = d.getDeweyDecimal();
}

code is off the top of my head. For more detail see
http://mindprod.com/jgloss/classforname.html
 
T

Thomas Hawtin

Eric said:
public class Book {}

public class Philosophy extends Book {
static int DeweyDecimal = 601;
^^^^^^In general a static variable should also be final.
}

public class JavaProgramming extends Book {
static int DeweyDecimal = 005; ^^^This is an octal constant!!
}

public class WebstersDictionary extends Book {
static int DeweyDecimal = 903;
}

Generally this sort of hiding is a bad idea.
Now, if I had an array I'd created off all the classes of books (e.g.
Book[] books = {Philosophy.class, JavaProgramming.class,
WebstersDictionary.class}) how would I go about getting the
DeweyDecimal number of one of the types of books without instantiating
them?

That array doesn't make any sense. Book[] is an array of books.
Class<Book>[] is an array of book types.

If you just need to find the DeweyDecimal number for a given book,
either add an abstract method to the Book base class and override, or
pass the number through the constructor.

If you need to manipulate types of book, it is far better to introduce a
type for the type of book rather than attempt to botch something up with
Classes and reflection. Something like (in 5.0):

/** @see Book */
enum BookType {
PHILOSOPHY(601) {
public Philosophy create() {
return new Philosophy();
}
},
JAVA_PROGRAMMING(5) {
public JavaProgramming create() {
return new JavaProgramming();
}
},
WEBSTER_DICTIONARY(903) {
public WebstersDictionary create() {
return new WebstersDictionary();
}
},
;
private final int deweyDecimal;
private BookType(int deweyDecimal) {
this.deweyDecimal = deweyDecimal;
}
public final int getDeweyDecimal() {
return deweyDecimal;
}
public abstract Book create();
}

Not the problem with Dewey Decimal representation differing from Java
ints. Possibly you may want to use a different type.

Tom Hawtin
 
I

Ingo R. Homann

Hi,
public class Book {}

public class Philosophy extends Book {
static int DeweyDecimal = 601;
}

public class JavaProgramming extends Book {
static int DeweyDecimal = 005;
}

public class WebstersDictionary extends Book {
static int DeweyDecimal = 903;
}

Now, if I had an array I'd created off all the classes of books (e.g.
Book[] books = {Philosophy.class, JavaProgramming.class,
WebstersDictionary.class}) how would I go about getting the
DeweyDecimal number of one of the types of books without instantiating
them?

First: your books-array will cause a compiler error. It must be one of
the following:

Class[] books = {Philosophy.class, JavaProgramming.class,
WebstersDictionary.class}

or

Books[] books={new Philiosopy(), new ...}

To your question: When using the first version, nothing is instantiated.
You can use Reflection (java.lang.reflect.*) for reading the
int-variables. Since those variables are static, you do dot need to
instantiate the classes.

Ciao,
Ingo
 
E

Eric

Hi Roedy,

Will have a look at BCEL, thanks for the pointer.

WRT the numbers array, I was trying to avoid exactly this issue, where
there are multiple arrays that have information about the classes and
each needs to be updated whenever a new class is added. It seems
cludgy and errorprone. Instead I'd love to able to just drop in a new
class of the appropriate type, and immediately be able to extract the
needed info from it (referring to the libary example, to be able to add
a new book, and have the application extract information such as the
dewey decimal number without being explicitly told).

The example code you provide instantiates each class which is what I
was hoping to avoid.

Thanks again for your reply and the info,

John
 
E

Eric

Good point about the static variable, I just wrote up the example code
of the top of my head, but you're certainly correct. I got the type of
the array wrong too, thanks for catching it.

The problem with an overridden abstract method is that I'd need to
instantiate the class to use it :-(. That ideally would have been my
approach, an abstract static method, but I don't think Java allows such
a beast.

The enum in 1.5 looks like it might be worth upgrading for.

Thanks!

Cliff
 
E

Eric

Hi Roedy,

Will have a look at BCEL, thanks for the pointer.

WRT the numbers array, I was trying to avoid exactly this issue, where
there are multiple arrays that have information about the classes and
each needs to be updated whenever a new class is added. It seems
cludgy and errorprone. Instead I'd love to able to just drop in a new
class of the appropriate type, and immediately be able to extract the
needed info from it (referring to the libary example, to be able to add
a new book, and have the application extract information such as the
dewey decimal number without being explicitly told).

The example code you provide instantiates each class which is what I
was hoping to avoid.

Thanks again for your reply and the info,

Cliff
 
E

Eric

Good point about the static variable, I just wrote up the example code
of the top of my head, but you're certainly correct. I got the type of
the array wrong too, thanks for catching it.

The problem with an overridden abstract method is that I'd need to
instantiate the class to use it :-(. That ideally would have been my
approach, an abstract static method, but I don't think Java allows such
a beast.

The enum in 1.5 looks like it might be worth upgrading for.

Thanks!

Eric
 
E

Eric

Hi Roedy,

Will have a look at BCEL, thanks for the pointer.

WRT the numbers array, I was trying to avoid exactly this issue, where
there are multiple arrays that have information about the classes and
each needs to be updated whenever a new class is added. It seems
cludgy and errorprone. Instead I'd love to able to just drop in a new
class of the appropriate type, and immediately be able to extract the
needed info from it (referring to the libary example, to be able to add
a new book, and have the application extract information such as the
dewey decimal number without being explicitly told).

The example code you provide instantiates each class which is what I
was hoping to avoid.

Thanks again for your reply and the info,

Eric
 
E

Eric

Hi Ingo,

Sorry about my earlier error, I'd prefer to use the Class[] books
array. Given the below code, how would I go about reading the values
of the int-variables? I looked at java.lang.reflect.*, but all
relevant methods seem to require an Object.

Thanks so much for your time.

---

public class BookTest {
public static void main(String[] args) {
Class[] books = new Class[]{Philosophy.class,
JavaProgramming.class, WebstersDictionary.class};
// use reflection here
}
}


class Book {
}


class Philosophy extends Book {
final static int DeweyDecimal = 601;
}


class JavaProgramming extends Book {
final static int DeweyDecimal = 005;
}


class WebstersDictionary extends Book {
final static int DeweyDecimal = 903;
}
 
R

Roedy Green

Hi Roedy,

Will have a look at BCEL, thanks for the pointer.

WRT the numbers array, I was trying to avoid exactly this issue, where
there are multiple arrays that have information about the classes and
each needs to be updated whenever a new class is added. It seems
cludgy and errorprone. Instead I'd love to able to just drop in a new
class of the appropriate type, and immediately be able to extract the
needed info from it (referring to the libary example, to be able to add
a new book, and have the application extract information such as the
dewey decimal number without being explicitly told).

The example code you provide instantiates each class which is what I
was hoping to avoid.

Thanks again for your reply and the info,

Eric
I am seeing each of your messages three times. Perhaps you are
posting multiple times thinking they did not take. Sometimes it takes
15 minutes or so for your news server to post newly received messages.
 

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,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top