How to access a member constant by FQN

S

Sideswipe

I am curious how, if it's possible, I can access a constant declared
in a class using only a fully qualified name

example:

package com.whatever.mycompany;

public class MyConstants {

public static final Integer MY_CONST = new Integer(10);
}


Object someConst = ...?

With this last line I would like to fully qualify the constant as
"com.whatever.mycompany.MyConstants.MY_CONST"

It isn't a class I am after but an instance of a class. How do you ask
the JVM for an existing instance in memory???

Thanks
 
E

Eric Sosman

Sideswipe wrote On 09/05/07 13:28,:
I am curious how, if it's possible, I can access a constant declared
in a class using only a fully qualified name

example:

package com.whatever.mycompany;

public class MyConstants {

public static final Integer MY_CONST = new Integer(10);
}


Object someConst = ...?

With this last line I would like to fully qualify the constant as
"com.whatever.mycompany.MyConstants.MY_CONST"

Object someConst =
com.whatever.mycompany.MyConstants.MY_CONST;

.... which seems so obvious that I suspect I've missed the
point of your question.
It isn't a class I am after but an instance of a class. How do you ask
the JVM for an existing instance in memory???

Now I'm *sure* I've missed something ... MY_CONST is
a reference variable, a static member of MyConstants. It
is initialized (when MyConstants is loaded) to refer to an
Integer object. The Integer exists in memory. When you
initialize someConst, another reference variable, it refers
to that same, already-existing Integer instance. What do
you find unsatisfactory about this state of affairs? (And
how does name qualification or lack thereof enter into the
picture?)
 
S

Sideswipe

Hmm, ok, let me try this:

Class.forName("com.whatever.mycompany.MyConstants");
// MyConstants is now loaded and the static members initialized

MY_CONST is now an Integer instance floating around in the JVM. So, I
don't NEED a new instance of it, but I want to access it by a fully
qualified name.

When I do: Class.newInstance() <-- object is returned but if I am
given the string: "com.whatever.mycompany.MyConstants.MY_CONST" I am
not being given a FQN to a class, I am being given a FQN to a static
final member of a Class.

Another way to say it, how do I make an assignment to this instance
based on the FQN as a String. This is all runtime/reflection -- not
compile time so I have no way to know what will be referenced. If I
knew the Outter class I could use reflection to get the fields and
discover it by name, but I can't know that the String given to me
represents a class and not one of it's members.

Object someConst = ?
 
J

Joshua Cranmer

Sideswipe said:
Hmm, ok, let me try this:

Class.forName("com.whatever.mycompany.MyConstants");
// MyConstants is now loaded and the static members initialized

MY_CONST is now an Integer instance floating around in the JVM. So, I
don't NEED a new instance of it, but I want to access it by a fully
qualified name.

When I do: Class.newInstance() <-- object is returned but if I am
given the string: "com.whatever.mycompany.MyConstants.MY_CONST" I am
not being given a FQN to a class, I am being given a FQN to a static
final member of a Class.

Another way to say it, how do I make an assignment to this instance
based on the FQN as a String.

I don't think you fully appreciate the definition of static final...

A static member is a member that exists for all instances of the class
and only one ever exists. [*] A final variable is a variable that cannot
be reassigned after it has been assigned once. Therefore, a static final
variable is an non-reassignable variable that only ever exists once. It
is for that reason that static final primitives, String's, and Class's
(?) are inlined into the code. Furthermore, the Integer class is
immutable, so none of its fields can change, so a static final Integer
is truly unchangeable.

> This is all runtime/reflection -- not compile time so I have no way to
> know what will be referenced. If I knew the Outter class I could use
> reflection to get the fields and discover it by name, but I can't know
> that the String given to me represents a class and not one of it's
> members.

Object someConst = ?

1. Why do you need to use reflection?
2. From where is the String given to you?
3. Why can the String given to you represent a field?
4. Why do you need to reassign a static final variable?

If you still desperately want to do this, note that of any identifier,
the simple name of the class will either appear as the rightmost, second
from the right, are not at all (see the JLS). It should become clear how
to proceed...

[*] This definition will fail to hold under two conditions: the class
information is collected by the GC, or the class is redefined using
multiple class loaders. The former is generally not of too much concern,
and the latter is only important when one is deeply involved with guts
of the system, which I assume you are not.
 
L

Lew

The answer is
com.whatever.mycompany.MyConstants.MY_CONST

There is no "new instance of it".
 
P

Patricia Shanahan

Sideswipe said:
Hmm, ok, let me try this:

Class.forName("com.whatever.mycompany.MyConstants");
// MyConstants is now loaded and the static members initialized

MY_CONST is now an Integer instance floating around in the JVM. So, I
don't NEED a new instance of it, but I want to access it by a fully
qualified name.

When I do: Class.newInstance() <-- object is returned but if I am
given the string: "com.whatever.mycompany.MyConstants.MY_CONST" I am
not being given a FQN to a class, I am being given a FQN to a static
final member of a Class.

Another way to say it, how do I make an assignment to this instance
based on the FQN as a String. This is all runtime/reflection -- not
compile time so I have no way to know what will be referenced. If I
knew the Outter class I could use reflection to get the fields and
discover it by name, but I can't know that the String given to me
represents a class and not one of it's members.

If I understand the problem, you have a String
"com.whatever.mycompany.MyConstants.MY_CONST" and want to access the
corresponding field.

You first need to split it into the fully qualified class name and the
field name. Use Class.forName to get a reference to the Class object.
Use the Class's getField method to get a reference to the Field object
for "MY_CONST". Take a look at the API documentation for Field to see
how to do specific operations on the Field, such as getting a reference
to the Integer.

Almost, but not quite, always this sort of reflection tangle is a
mistake, and there is a simpler, cleaner solution. It may be worth
describing the problem you are trying to solve with all this.

Patricia
 
S

Sideswipe

I don't think you fully appreciate the definition of static final...

I do fully appreciate what those qualifiers mean. I now can see how
you got confused. Ok, let's take the case
where I know this FQN at compile time. I could then do this:

Object myObj = com.whatever.mycompany.MyConstants.MY_CONST;

This is perfectly valid and trivial

Now say I only have the above as a string representing the fully
qualified name?


I could do:
Object myObj = null;
Class c = Class.forName("com.whatever.mycompany.MyConstants");

Field f = c.getField("MY_CONST");
myObject = f.get(null);

But that would be only possible if I knew that Containing class and
the member I needed.
1. Why do you need to use reflection?
Do you know of a way to access member fields at runtime without
knowing their names?
2. From where is the String given to you?
A database? XML? Commandline? Does it matter?
3. Why can the String given to you represent a field?
I assume you mean "can't" -- and indeed it does or may
4. Why do you need to reassign a static final variable?
I don't, miscommunication issue. See above
If you still desperately want to do this, note that of any identifier,
the simple name of the class will either appear as the rightmost, second
from the right, are not at all (see the JLS). It should become clear how
to proceed...

If I assume that the string passed to me is a member field, I can do
that above reflection. But, such a String could represent a fully
qualified class name. At which point moving back one '.' would put me
at the package level. Can I determine if a FQN is a Class or a Field
in a Class? I know that, when referring to inner classes they are
"com.blah.MyClass$Inner" -- but this isn't an inner class.



I suppose I need a concrete example to really show people that despite
honest bonifide credentials on this subject I am not a rookie. So,
Here goes

public class MyConstants {

public static final SomeInterface CONST1 = new SomeSubtype() {
public void interfaceMethod() {}
};

public static final SomeInterface CONST2 = new SomeSubtype() {
public void interfaceMethod() {}
};

public static final SomeInterface CONST3 = new SomeSubtype() {
public void interfaceMethod() {}
};

}

SomeInterface x = MyConstants.CONST1; // trivial.

SomeInterface X = ..? // do the above given only this string:
"MyConsts.CONST1"; // This string is passed at runtime
 
R

Roedy Green

With this last line I would like to fully qualify the constant as
"com.whatever.mycompany.MyConstants.MY_CONST"

It isn't a class I am after but an instance of a class. How do you ask
the JVM for an existing instance in memory???

I think you are using the word "instance" incorrectly. If you truly
meant instance you would have to say something like

TheClass anInstance = new TheClass();

Object x = anInstance.MY_CONST;

If you what you mean is a fully qualify class you must either import
that class, possibly import static. Or fully qualify the reference
e.g.

Integer x = com.whatever.mycompany.MyConstants.MY_CONST;

see http://mindprod.com/jgloss/import.html
http://mindprod.com/jgloss/package.html
 
M

Mark Space

Sideswipe said:
SomeInterface X = ..? // do the above given only this string:
"MyConsts.CONST1"; // This string is passed at runtime

My gut feeling is... if you need "MyConstants" and you get passed
"MyConstants.CONST1" you've been supplied an incorrect parameter.

You write a function. You need to be passed a 3. Someone passes you a
4. This is wrong. You could subtract one from four to get three, but
then if you *ARE* passed a 3 you'd end up with a 2, and this is wrong.
How do you solve this dilemma?

Throw an error if you get passed something besides a 3. Anything else
is incorrect, it's that simple.

I guess you could try to instantiate the string you get. If it doesn't
go, try stripping off one "." and try again. That's all I can think of.
You could also, I suppose, search through the class path and try to
ID which parts of the string are package and which parts are class. You
are just duplicating the effort that the classloader will make when you
try to instantiate a class tho, I think.

If you have more control over your input, pass two parameters. The
first is the class, the second is a field. The second parameter can be
null or "". That's the only other idea I got.
 
S

Sideswipe

Patricia,
From my prior post I did offer that as a solution I just wasn't sure
there wasn't something easier. But you have correctly identified what
I was trying to ask. I didn't realize it would be so hard. Often times
I ask questions in this group not because I want to implement said
question, but because I am trying to see if it's even possible. Part
of the way I learn is to always push the boundries of what I know is
possible.

Thanks for confirming my suspicions.

Christian Bongiorno
 

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

No members online now.

Forum statistics

Threads
473,989
Messages
2,570,207
Members
46,782
Latest member
ThomasGex

Latest Threads

Top