Paradox of automatic type wrapping and reflection?
Hello all,
I justify the "paradox" in the title later on. I have a class, let FileHandlerCU that has a method with the following signature:
publicboolean computationUnits.FileHandlerCU.WriteLineAtEnd(java.lang.String)
Please consider the following code fragment:
//inside main
Class aClass = computationUnits.FileHandlerCU.class;
//index 1 corresponds to WriteLineAtEnd method
Method m = aClass.getDeclaredMethods()[1];
Class returnTypeClass = m.getReturnType();
try{
Class.forName(returnTypeClass.getName());
}catch (ClassNotFoundException e){
//if one class's name is a primitive type, for example boolean
e.printStackTrace();
}
From this code, the following exception is thrown (recall that the output parameter of this method is the primitive type boolean):
java.lang.ClassNotFoundException:boolean
because no such class with name "boolean" exists!
Well, isn't it a paradox that we can NOT actually write the code: Class.forName(someClass.getName()), even when someClass is a properly instantiated class instance?! This should be an axiom of the Abstract Data Type "Class", shouldn't it?
My question is whether there is a "neat" way to overcome this problem rather than simply using a large if-then-else statement for primitive types. You know, something like:
if(someClass.getName().equals(boolean)){
return java.lang.Boolean.class;
}elseif ...
}else{
return Class.forName(someClass.getName());
}
Do I need to play with class loaders? (how?)
One might wonder "why would youever write this code?". Fair point. You can skip the following staff if you don't want my justification. I am not using this code as it is. I am storing the method parameter types inside an XML file (using the someClass.getName() method). Later on, I use this XML file for creating MyMethod (see below) objects, and I am using the stored class name inside the XML file to get the classes of the I/O parameters. Yeah, I know, I am doing all kind of weird staff in my code. MyMethod looks like this:
publicclass MyMethod{
privatefinal String name;
privatefinal Vector<Class> inputParams =new Vector<Class>(2);
privatefinal Vector<Class> outputParams =new Vector<Class>();
....
}
Message was edited by:
ntalamai
[3556 byte] By [
ntalamaia] at [2007-11-27 11:14:55]

# 1
So, is it that you want to go from the String "boolean" to the Class object boolean.class, just as you can use Class.forName("java.util.Date") to go from the String "java.util.Date" to the class java.util.Date.class?
I don't know of a way to do it as cleanly as you like. About the best I can think of is to have a map whose keys are the primitives' names and whose values are their respective Class objects. If get(name) returns non-null, use that Class object. If it returns null, use Class.forName(name)
jverda at 2007-7-29 14:09:48 >

# 2
> > if(someClass.getName().equals(boolean)) {
>return java.lang.Boolean.class;
By the way, if you were to go with this approach, it would be boolean.class, not java.lang.Boolean.class.
jverda at 2007-7-29 14:09:48 >

# 3
Well, there is no class called 'boolean', as such. I'll point you toward java.lang.Boolean.TYPE, which is close enough to being boolean's "class", but it's not quite a true class as we know it
In general, reflection and primitives don't mix well, as you're finding.
# 4
> because no such class with name "boolean" exists!
It does exist. You just can't get it with Class.forName.
boolean.class.getName() gives "boolean"
jverda at 2007-7-29 14:09:48 >

# 5
> > because no such class with name "boolean" exists!
>
> It does exist. You just can't get it with
> Class.forName.
>
> boolean.class.getName() gives "boolean"
Fair point. Does that mean it exists, or that the runtime is doing some jiggery-pokery, like it does with array classes, though? Not really sure here
# 6
> > > because no such class with name "boolean" exists!
>
> >
> > It does exist. You just can't get it with
> > Class.forName.
> >
> > boolean.class.getName() gives "boolean"
>
> Fair point. Does that mean it exists, or that the
> runtime is doing some jiggery-pokery, like it does
> with array classes, though? Not really sure here
The Class object representing the boolean type certainly exists. But that doesn't mean boolean is a class.
jverda at 2007-7-29 14:09:48 >

# 7
> > > > because no such class with name "boolean"
> exists!
> >
> > >
> > > It does exist. You just can't get it with
> > > Class.forName.
> > >
> > > boolean.class.getName() gives "boolean"
> >
> > Fair point. Does that mean it exists, or that the
> > runtime is doing some jiggery-pokery, like it does
> > with array classes, though? Not really sure here
>
>
>
> The Class object representing the boolean type
> certainly exists. But that doesn't mean boolean is a
> class.
So it is a paradox!
Really, it's a side-effect of primitives not extending java.lang.Object, I suppose. When playing with non-trivial reflection, you often lament the compromises Java makes in OO terms, I find. You've got 4 basic types: primitives, objects, arrays and now enums, and they all need separate handling in reflective code. What a nuisance!
# 8
> So it is a paradox!
I don't see it as one. An inconsistency or an exception to the rule at worst.
> Really, it's a side-effect of primitives not
> extending java.lang.Object, I suppose. When playing
> with non-trivial reflection, you often lament the
> compromises Java makes in OO terms, I find. You've
> got 4 basic types: primitives, objects, arrays and
> now enums, and they all need separate handling in
> reflective code. What a nuisance!
I've never reflected on enums, and the few times I have on arrays, it hasn't been more than a minor inconvenience.
jverda at 2007-7-29 14:09:48 >

# 9
ntalamai wrote:
> From this code, the following exception is thrown (recall that the output
> parameter of this method is the primitive type boolean):
>
> java.lang.ClassNotFoundException: boolean
>
> because no such class with name "boolean" exists!
>
> Well, isn't it a paradox that we can NOT actually write the code:
> Class.forName(someClass.getName()), even when someClass is a properly
> instantiated class instance?! This should be an axiom of the Abstract
> Data Type "Class", shouldn't it?
I would say it is paradox. The Javadoc for Class.getName says that it
"Returns the Class object associated with the class or interface with the
given string name, using the given class loader. Given the fully qualified
name for a class or interface (in the same format returned by getName) this
method attempts to locate, load, and link the class or interface."
But according to the Java language specs, e.g. "boolean" is the
fully-qualified name of the primitive type boolean (as returned by
Boolean.TYPE.getName()). Continuing with the Javadoc:
"If name denotes a primitive type or void, an attempt will be made to
locate a user-defined class in the unnamed package whose name is name.
Therefore, this method cannot be used to obtain any of the Class objects
representing primitive types or void."
So, if this user-defined class (e.g. "boolean" again) actually exists (though
it cannot be created with Java because of the boolean keyword), it is
loaded, and has the fully-qualified name... "boolean", right? Now you have two
different Class objects (and even worse, one denoting a primitive
type, and the other a reference type) with teh same fully-qualified
name. Now to me, the whole thing is paradoxical. Why didn't they choose unambiguous
class names for the primitive types, like ".[<-dot]boolean"?
georgemc wrote:
> > > because no such class with name "boolean" exists!
> >
> > It does exist. You just can't get it with
> > Class.forName.
> >
> > boolean.class.getName() gives "boolean"
>
> Fair point. Does that mean it exists, or that the runtime is doing some
> jiggery-pokery, like it does with array classes, though? Not really sure here
The expression boolean.class is replaced with Boolean.TYPE by javac.
And the Javadoc for Class.isPrimitive, it just say that the Class objects
for the primitive types "[...] may only be accessed via the following
public static final variables, and are the only Class objects for which this
method returns true. Boolean.TYPE, Character.TYPE, [...]" and so on. As you
already said
> In general, reflection and primitives don't mix well, as you're finding.
But this probably also what makes primitive types, well, primitive.
Their instances are, in fact, not able to reflect about themselves.
But there's also no need for, because in Java, you cannot encounter an instance of
a primitive type without knowing its type in the first place (for that very
reason, because one would have no way to tell, and the JVM wouldn't, either).
It's simply not possible to get hold of one and invoke a method on it to
say: "Hey data, what's your type?" aka getClass(). Primitive types are always
concrete, while reference types could be considered abstract, in a way. If you
just have Object anObject, you don't know what you got, really, until you
reflect. Anyway, this doesn't help with reflecting primitve formal parameters,
does it? I'll take my meds now.
georgemc wrote:
> You've got 4 basic types: primitives, objects, arrays and now enums, and they
> all need separate handling in reflective code. What a nuisance!
From my recent adventures with enums, I'd probably disagree. Enums are ordinary
Java class, no enum component types or something array-like,
"But it's an Enum", yes, but then there's also interfaces, abstract classes,
inner classes (not to forget annotations) etc. All those features have their
special Class.isWhatever method, an access flag in the class file header
and other extra stuff maybe, but don't necessarily require separate handling
in reflective code per se, I'd say. Only if you are interested in a particular
property. Maybe I didn't get the idea, though...
# 10
>> So it is a paradox!
>I don't see it as one. An inconsistency or an exception to the rule at worst.
What is the benefit of having such an inconsistency/ exception? This leads to confusion and some nasty side-effects, as pointed out:
> So, if this user-defined class (e.g. "boolean" again) actually exists (though
> it cannot be created with Java because of the boolean keyword), it is
> loaded, and has the fully-qualified name... "boolean", right? Now you have
> two
> different Class objects (and even worse, one denoting a primitive
> type, and the other a reference type) with teh same fully-qualified
> name. Now to me, the whole thing is paradoxical. Why didn't they choose
> unambiguous
> class names for the primitive types, like ".[<-dot]boolean"?
and
> In general, reflection and primitives don't mix well, as you're finding.
and
(in the Javadoc)
"If name denotes a primitive type or void, an attempt will be made to
locate a user-defined class in the unnamed package whose name is name."
How is this possible? Even in the unnamed package it is impossible to define "public class boolean"! Or am I missing something here?
My point is if there is a strong motivation for allowing this paradox/ inconsistency/ exception? I agree that it is nice to have classes denoting primitive types. This allows us to write things like:
Class [] params = aMethod.getParameterTypes(), without caring if the the parameters are arrays, objects, primitives, etc.
One the other hand simplicity and uniformity in the API is valuable. What does it mean that: Class.forName(someClass.getName()).equals(someClass)
is true for some (types of) classes, while it is not for others? For example consider the Stack abstract data type (which can be realised through a Java Object). The following is an axiom on its operations:
pop(push(some_data))=some_data
(without concurrency of course).
If this does not hold for forName-getName there must be a (good) reason, otherwise, according to my humble opinion, it is unacceptable.
# 11
> >> So it is a paradox!
>
> >I don't see it as one. An inconsistency or an
> exception to the rule at worst.
>
> What is the benefit of having such an inconsistency/
> exception?
The ability to have true primitive types in the language, so by implication, efficiency. It's not ideal, I agree
>This leads to confusion and some nasty
> side-effects, as pointed out:
> > So, if this user-defined class (e.g. "boolean"
> again) actually exists (though
> > it cannot be created with Java because of the
> boolean keyword), it is
> > loaded, and has the fully-qualified name...
> "boolean", right? Now you have
> > two
> > different Class objects (and even worse, one
> denoting a primitive
> > type, and the other a reference type) with teh
> same fully-qualified
> > name.
Not with the same simple name, let alone fully-qualified name:
boolean
java.lang.Boolean
See? Not the same
> Now to me, the whole thing is paradoxical.
> Why didn't they choose
> > unambiguous
> > class names for the primitive types, like
> ".[<-dot]boolean"?
They are unambiguous, as shown above
> b]and
> > In general, reflection and primitives don't mix
> well, as you're finding.
> b]and
> (in the Javadoc)
> "If name denotes a primitive type or void, an attempt
> will be made to
> locate a user-defined class in the unnamed package
> whose name is name."
>
> How is this possible? Even in the unnamed package it
> is impossible to define "public class boolean"! Or am
> I missing something here?
The runtime manages this. While, as Jeff said, there does exist a boolean class object, it is synthesized by the runtime as needed, rather than loaded. Which presumably explains why Class.forName can't get hold of it
> My point is if there is a strong motivation
> for allowing this paradox/ inconsistency/ exception?
> I agree that it is nice to have classes denoting
> primitive types. This allows us to write things like:
>
> Class [] params = aMethod.getParameterTypes(),
> without caring if the the parameters are arrays,
> objects, primitives, etc.
>
> One the other hand simplicity and uniformity in the
> API is valuable. What does it mean that:
> Class.forName(someClass.getName()).equals(someCl
> ass)
> is true for some (types of) classes, while it is
> not for others? For example consider the
> Stack abstract data type (which can be
> realised through a Java Object). The following is an
> axiom on its operations:
> pop(push(some_data))=some_data
(without
> concurrency of course).
>
> If this does not hold for forName-getName there must
> be a (good) reason, otherwise, according to my humble
> opinion, it is unacceptable.
Well, if it's unacceptable I'd be quite interested in seeing what you do about it.
# 12
I still don't see any paradox.
jverda at 2007-7-29 14:09:48 >

# 13
> >> So it is a paradox!
>
> >I don't see it as one. An inconsistency or an
> exception to the rule at worst.
>
> What is the benefit of having such an inconsistency/
> exception?
What the benefit is--or even whether there is or is not any benefit at all--has nothing whatsoever to do with whether it's a paradox. It can be horribly detrimental and still not be a paradox.
jverda at 2007-7-29 14:09:48 >

# 14
georgemc wrote:
> > [...]
> > [...] "boolean", right? Now you have two different Class objects
> > (and even worse, one denoting a primitive type, and the other a
> > reference type) with teh same fully-qualified name.
>
> Not with the same simple name, let alone fully-qualified name:
>
> boolean
> java.lang.Boolean
>
> See? Not the same
I think you got me wrong. jav.lang.Boolean, strictly speaking, has
little to do with the actual primitve type "boolean". It is just
an ordinary Java class extending java.lang.Object, that happens to
contain declare field TYPE, which hold the Class that represents the
"boolean" type, and is further used to wrap primitive booleans so
they can be handled like reference types. But there's no magic behind
the scences with java.lang.Boolean (well, except the initialization
of TYPE field, maybe).
What I meant above is that you actually have two types with the
same fully qualified name, but different class objects. This is even
considered in the Class.forName Javadoc cited!
Of course, as I said, it is impossible to compile a type with the
name "boolean" in the default (unnamed) package with the Java
language itself, because "boolean" is a keyword and thus the
class won't compile. But that doesn't mean that such a class
cannot exist at the JVM level. You can actually create it with
a Bytecode engineering library, e.g. ObjectWeb's ASM, in just about
two dozen lines of code. It exists, and can be loaded, showing the
behaviour described.
# 15
> georgemc wrote:
> > > [...]
> > > [...] "boolean", right? Now you have two
> different Class objects
> > > (and even worse, one denoting a primitive type,
> and the other a
> > > reference type) with teh same fully-qualified
> name.
> >
> > Not with the same simple name, let alone
> fully-qualified name:
> >
> > boolean
> > java.lang.Boolean
> >
> > See? Not the same
>
> I think you got me wrong. jav.lang.Boolean, strictly
> speaking, has
> little to do with the actual primitve type "boolean".
> It is just
> an ordinary Java class extending java.lang.Object,
> that happens to
> contain declare field TYPE, which hold the Class that
> represents the
> "boolean" type, and is further used to wrap primitive
> booleans so
> they can be handled like reference types. But there's
> no magic behind
> the scences with java.lang.Boolean (well, except the
> initialization
> of TYPE field, maybe).
>
> What I meant above is that you actually have two
> types with the
> same fully qualified name, but different class
> objects. This is even
> considered in the Class.forName Javadoc cited!
>
> Of course, as I said, it is impossible to co
I don't see how what you just said makes any difference to the fact that "boolean" and "java.lang.Boolean" are not the same name, or fqn
# 16
georgemc wrote:
> I don't see how what you just said makes any difference to the fact that "boolean"
> and "java.lang.Boolean" are not the same name, or fqn
Mmh, maybe I misunderstood what you were saying. Type "boolean" and java.lang.Boolean
are, obviously, two distinct types, I definitely don't doubt that -- but it was
not put into question either. This thread originated around the paradox, or let's call
it strange behaviour, when trying to load a primitiv type by its fully qualified
name (as returned by Class.getName) using Class.forName.
Now to explain why I consider the issue a paradox, I gave an example in my
post #9, to which you replied then. But java.lang.Boolean is not really involved
in the whole thing, except that exports a static field called TYPE, which
holds a reference to the Class object representing the primitive type "boolean".
I think we're talking at cross-purposes, so I'll try to clarify:
The OP reflected a method with return type primitive boolean.
The Class object returned by Method.getReturnType is a special object
representing the primitve type "boolean" (which can also be accessed via
java.lang.Boolean.TYPE, but let's leave that aside for now).
When invoking Class.getName on that object, it returns "boolean", because
the fully qualified class name of primitive types is equal to their Java
language keyword (see JLS, section 6.7).
Now, the OP tried to load the class using Class.forName, with that very FQN,
but that throws ClassNotFoundException, because a user-defined class
with that name in the default (unnamed) package does not exist on his/her
machine.
What I was trying to get across is that if such a type existed on his machine,
it would be loaded instead of teh class for the primitve type "boolean".
So you end up with two classes with the same FQN, and wouldn't even notice
without further investigation:
1) the primitve class "boolean"
2) the user-defined class "boolean" in the default (unnamed) package
Although being different types, both return "boolean" when invoking Class.forName
(as they actually have the same FQN). Otherwise they show some differnces naturelly
(e.g. isPrimitve, getSuperclass etc). This is totally indepenent of the type
java.lang.Boolean.
ntalamai wrote:
> [...]
> My point is if there is a strong motivation for allowing this paradox/ inconsistency/
> exception? I agree that it is nice to have classes denoting primitive types. This allows
> us to write things like:
>
> Class [] params = aMethod.getParameterTypes(),
>
> without caring if the the parameters are arrays, objects, primitives, etc.
>
> One the other hand simplicity and uniformity in the API is valuable.
> What does it mean that:
>
> Class.forName(someClass.getName()).equals(someClass)
>
> is true for some (types of) classes, while it is not for others?
> [...]
Well, after all, I think they just had to draw the line somewhere. You need the classes
representing primitve types to ease reflection, but when Class.forName would map
primitve type names to Class objects, too, you wouldn't be sure what you are dealing
with until you check again (isPrimitive?). And this would probably cause confusion in
other use cases of Class.forName (e.g when you'd actually use the Class returned to
create new instances) ...
# 17
So what you're saying is, if we use BCEL or something to synthesize a class with the fully-qualified name of "boolean" we may run into trouble? Not in the least. In the highly unlikely situation that you managed that or bothered to try, there's no way the runtime would load such a class before "loading" the primitive type "boolean". The nature of classloading in Java would ensure it was loaded long before any of your own code made it into memory. The bootstrap classloader will have loaded a bunch of classes long before then, then the system classloader will load the rest of java.lang (and some others, I believe) and unless by some massive fluke there isn't any use of the boolean type anywhere in java.lang.Object or any of it's dependencies, the primitive boolean class object is loaded. That's presuming there is such a thing. The class object for the boolean primitive type isn't loaded by any classloader accessible by user code, the runtime creates it. I don't know when. But the situation you've outlined is impossible, and therefore not really a problem. The primitive types will almost certainly be created by the bootstrap loader, or before it gets created.
Try this. Write a class called Object, in a package called java.lang. Give it a main method, and try to run it.
No way the runtime is going to allow you to define a class that prevents it having a primitive type available
# 18
> Well, after all, I think they just had to draw the line somewhere. You need the classes
> representing primitve types to ease reflection, but when Class.forName would map
> primitve type names to Class objects, too, you wouldn't be sure what you are dealing
> with until you check again (isPrimitive?). And this would probably cause confusion in
> other use cases of Class.forName (e.g when you'd actually use the Class returned to
> create new instances) ...
That makes sense.
> So what you're saying is, if we use BCEL or something
> to synthesize a class with the fully-qualified name
> of "boolean" we may run into trouble? Not in the
> least. In the highly unlikely situation that you
> managed that or bothered to try, there's no way the
> runtime would load such a class before "loading" the
> primitive type "boolean".
> [...]
> But the situation you've outlined is impossible, and
> therefore not really a problem. The primitive types
> will almost certainly be created by the bootstrap
> loader, or before it gets created.
If this is the case, what is the point in specifying in Javadoc:
> If name denotes a primitive type or void, an attempt will be made to locate a
> user-defined class in the unnamed package whose name is name.
I guess JVM checks at runtime that never two types may have the same FQN (?). (What is the fqn of the class representing the primitive boolean? It cannot be "boolean" can it?) On the other hand, two different class loaders can be used for loading classes with the same name because each class is uniquely identified by the pair <class, classloader> right? So in principle, it is possible to get the situation described by oebert. (Please correct if I am wrong).
Regarding the paradox.. I think the self-contradiction arose when I considered the documentation of only "String getName()" and "Class.forName(String)": nowhere is mentioned what happens to primitive types. But "Class.forName(String, boolean, ClassLoader)" specifies this case and dissolves the confusion. So the moral of the story (at least for me) is to read the specification of all methods if one is implemented in terms of another.
# 19
> If this is the case, what is the point in specifying
> in Javadoc:
> > If name denotes a primitive type or void, an
> attempt will be made to locate a
> > user-defined class in the unnamed package whose
> name is name.
Because that is it's behaviour, and should be documented as such. In effect, although there exists class objects for the primitive types, they are not reachable via a classloader. So the classloader behaves as it always does and tries to load the class by name. Which can't exist, unless someone's gone to some trouble to create it in which case they deserve everything they get!
> I guess JVM checks at runtime that never two types
> may have the same FQN (?). (What is the fqn of the
> class representing the primitive boolean? It cannot
> be "boolean" can it?)
What else would it be?
> On the other hand, two
> different class loaders can be used for loading
> classes with the same name because each class is
> uniquely identified by the pair <class, classloader>
> right? So in principle, it is possible to get the
> situation described by oebert. (Please correct if I
> am wrong).
You may be able to get to that situation using a bytecode enhancer such as BCEL or ASM, but the primitive types are keywords so no compiler will let you create such a class. I haven't tried to synthesize such a class though, so I don't know what would happen. I doubt the runtime would cope with it, and probably just die. Try creating a class called java.lang.Object, and see what happens :-)
> Regarding the paradox.. I think the
> self-contradiction arose when I considered the
> documentation of only "String getName()" and
> "Class.forName(String)": nowhere is mentioned what
> happens to primitive types. But
> "Class.forName(String, boolean, ClassLoader)"
> specifies this case and dissolves the confusion. So
> the moral of the story (at least for me) is to read
> the specification of all methods if one is
> implemented in terms of another.
I've lost sight of why this question arose. Did you experience a problem regarding this, or are you just curious?
# 20
> > If this is the case, what is the point in
> specifying
> > in Javadoc:
> > > If name denotes a primitive type or void, an
> > attempt will be made to locate a
> > > user-defined class in the unnamed package whose
> > name is name.
>
> Because that is it's behaviour, and should be
> documented as such. In effect, although there exists
> class objects for the primitive types, they are not
> reachable via a classloader. So the classloader
> behaves as it always does and tries to load the class
> by name. Which can't exist, unless someone's gone to
> some trouble to create it in which case they deserve
> everything they get!
>
>
> > On the other hand, two
> > different class loaders can be used for loading
> > classes with the same name because each class is
> > uniquely identified by the pair <class,
> classloader>
> > right? So in principle, it is possible to get the
> > situation described by oebert. (Please correct if
> I
> > am wrong).
>
> You may be able to get to that situation using a
> bytecode enhancer such as BCEL or ASM, but the
> primitive types are keywords so no compiler will let
> you create such a class. I haven't tried to
> synthesize such a class though, so I don't know what
> would happen. I doubt the runtime would cope with it,
> and probably just die. Try creating a class called
> java.lang.Object, and see what happens :-)
>
So in principle it is possible to create a class with name "boolean", etc. :-) Although you deserve what you get. Agree.
> > I guess JVM checks at runtime that never two types
> > may have the same FQN (?). (What is the fqn of the
> > class representing the primitive boolean? It
> cannot
> > be "boolean" can it?)
>
> What else would it be?
packageName.boolean or is class "boolean" part of the top-level package? (JLTS 6.7)
> > Regarding the paradox.. [...]
>
> I've lost sight of why this question arose. Did you
> experience a problem regarding this, or are you just
> curious?
I had a problem. Could not essentially do Class.forName(someClass.getName()) for classes that I had obtained through reflection. See my first post for more details why this could have been useful.
# 21
> So in principle it is possible to create a class with
> name "boolean", etc. :-) Although you deserve what
> you get. Agree.
I'm really not sure. No way to know without trying it, I suppose
> > > I guess JVM checks at runtime that never two
> types
> > > may have the same FQN (?). (What is the fqn of
> the
> > > class representing the primitive boolean? It
> > cannot
> > > be "boolean" can it?)
> >
> > What else would it be?
>
> packageName.boolean or is class "boolean" part of the
> top-level package? (JLTS 6.7)
It's not part of any package. Although the class does exist, it's not subject to the same treatment by the runtime as other classes. I don't think "packages" would make any sense here
> > > Regarding the paradox.. [...]
> >
> > I've lost sight of why this question arose. Did
> you
> > experience a problem regarding this, or are you
> just
> > curious?
>
> I had a problem. Could not essentially do
> Class.forName(someClass.getName()) for classes that I
> had obtained through reflection. See my first post
> for more details why this could have been useful.
Quite. You're going to run into similar issues when dealing with arrays, too
# 22
Well, I thought that (at least in my last post), I made my point quite clear by giving a step
by step description of the procedure leading to said "paradox" (or whatever you call it). I wonder how,
from reading my posts, would one get the idea that I wanted to trick the VM into loading a user-defined
type (either while bootstrapping or later) to replace the primitive type "boolean"? Because this
is most certainly not my intention, and you'll have to show me how these assumptions are justified
by what I posted, then. I've been talking about the issue raised in the original post, right from
the start.
In addition, there is already some redundancy here. Actually, the whole matter is carefully worded
in the Javadoc for Class.forName, which, by now, has been cited a few times. I just added my own
thoughts to the initial citations.
Basically, I just used this "user-defined boolean class" thing to explain why I considered the
issue the OP stumbled across as paradoxical, that's all. So I agree with what
ntalamai wrote:
> So in principle it is possible to create a class with name "boolean", etc. :-) Although you deserve
> what you get. Agree.
And of course, not relevant in day-to-day development, but like in most programming languages,
there's lots(?) of other bad stuff that one can do with Java (plus some dark corners), but usually shouldn't.
And whether it is regarded as a nonissue or not may be debatable, I'm not concerned.
The only non-redundant information I can add is some source code, which I will do below -- although it is
not particularly entertaining and doesn't provide any new insights beyond what has already been discused
here, and what is written in the Javadoc cited, and the JLS; and you'll have to download the ASM jar to
get it to run, but anyway... here we go:
1) Download ASM jar (asm-3.0.jar) and place in classpath
http://forge.objectweb.org/project/download.php?group_id=23&file_id=7264
2) (copy & paste) This is the java program that creates a class with the fully-qualified class
name "boolean". It's no big deal, really, as you can see. "boolean" is a valid class name (yeah,
not in the Java compiler, so to speak, but on the Java platform). And the fully qualified name
of a class in the default (unnamed) package is its simple name. "boolean". It's not forbidden to
have such a type, even in the Java language. It just happens taht you cannot compile it with a
Java compiler because of the "boolean" keyword (I know i repeat myself).
This will create a file called "boolean.class" in the current working dir!
(ASM Javadoc: http://asm.objectweb.org/current/doc/javadoc/user/index.html)
// Construct_boolean.java
import java.io.*;
import org.objectweb.asm.*;
public class Construct_boolean implements Opcodes {
public static void main(final String[] args)
throws Throwable
{
final ClassWriter cw = new ClassWriter(0);
cw.visit(V1_2, ACC_PUBLIC, "boolean", null, "java/lang/Object", null);
// create members here...
cw.visitEnd();
final byte[] data = cw.toByteArray();
final FileOutputStream classFile = new FileOutputStream("boolean.class");
classFile.write(data);
classFile.close();
}
}
3) Now that everything is set up, here comes demo (c&p). You have to have "boolean.class"
on the -cp in default (unnamed) package for this to work, of course.
// Load_boolean.java
public class Load_boolean {
public static void main(final String[] args)
throws Throwable
{
final Class userDefined_boolean = Class.forName(boolean.class.getName());
System.out.println("Loaded user-defined type 'boolean':\n");
System.out.println("Class.forName(boolean.class.getName()).toString(): "
+ userDefined_boolean.toString() );
System.out.println(" .getName(): "
+ userDefined_boolean.getName() );
System.out.println(" .isPrimitive(): "
+ userDefined_boolean.isPrimitive() );
System.out.println(" .getSuperclass(): "
+ userDefined_boolean.getSuperclass() );
// ...
System.out.println("\nBoolean.TYPE aka boolean.class.toString(): "
+ boolean.class.toString());
System.out.println(".getName(): "
+ boolean.class.getName() );
System.out.println(".isPrimitive(): "
+ boolean.class.isPrimitive() );
System.out.println(".getSuperclass(): "
+ boolean.class.getSuperclass() );
System.out.println("\nboolean.class == Class.forName(boolean.class.getName()): " +
(boolean.class == userDefined_boolean) );
}
}
This is not very spectacular and merely demonstrates what has already been mentioned.
I'm not posting the output, because it should be equal on any compliant JVM (hopefully).
One conclusion might be that whenever you succeed in loading a Class via Class.forName,
you can be sure that it is not represents a primitve type, and you are allowed to create
instances etc.
Re-reading this thread, I'm not sure anymore if I would still call it a paradox, after all,
as you can, e.g. achieve similar thing with different class loaders and other reference types,
as was brought up by ntalamai. Haven't looked at it this way. What's special/confusing here
is probably that you have a reference type with the same FQN as a primitive type. Oh well,
whatever, it was fun to investigate... Let's switch to Smalltalk, then? (just kidding)
# 23
Jebus wept, oebert! Can I just ask at this point, who and what t is exactly that you're arguing with and about here?
# 24
Mmh, so let's add even more white noise. From my part it wouldn't have been necessary to spread
this out like it has been now, because it isn't that complicated, is it? But you replied to several
posts of mine, getting wrong what I wrote (on purpose, I have to ask now?); so I just tried to gradually
clarify things, because I assumed you were honestly interested in the issue -- I am, for sure. If you
wanted to trick me into overly elaborating the whole matter, you succeeded. But I will stop here now.
# 25
> Mmh, so let's add even more white noise. From my part
> it wouldn't have been necessary to spread
> this out like it has been now, because it isn't that
> complicated, is it? But you replied to several
> posts of mine, getting wrong what I wrote (on
> purpose, I have to ask now?); so I just tried to
> gradually
> clarify things, because I assumed you were honestly
> interested in the issue -- I am, for sure. If you
> wanted to trick me into overly elaborating the whole
> matter, you succeeded. But I will stop here now.
Yes, lets stop here. You seem determined that there should be an argument and I can't be bothered
# 26
> packageName.boolean or is class "boolean" part of the
> top-level package? (JLTS 6.7)
boolean is not a class.
There exists the class String. It is in the java.lang package.
There exists the instance of Class, java.lang.String.class. It is an instance, not a class, and hence not in a package.
There does not exist any class boolean.
There exists the instance of Class, boolean.class. It is an instanc,e not a class, and hence not in a package.
> I had a problem. Could not essentially do
> Class.forName(someClass.getName()) for classes that I
> had obtained through reflection. See my first post
> for more details why this could have been useful.
Is the map workaround that I suggested sufficient for your needs?
jverda at 2007-7-29 14:09:53 >

# 27
I haven't read most of the posts before me because [snore], but, Class.forName() returns a Class doesn't it? And you got the parameters for that method from a Class object, so why are you bothering with Class.forName()?
Also, in my experience when faced with a primitive datatype it returns the Class version of that datatype, because the .getReturnType() method returns a Class and therefore couldn't possibly return a primitive.
Lastly, all the Class versions of the primitive datatypes have the same name but with the first letter capitalised. So couldn't you just capitalise the first letter of the returnTypeClass.getName() string?
# 28
> > packageName.boolean or is class "boolean" part of
> the
> > top-level package? (JLTS 6.7)
>
> boolean is not a class.
>[...]
> There exists the instance of Class,
> java.lang.String.class. It is an instance, not a
> class, and hence not in a package.
>
> There does not exist any class boolean.
>
> There exists the instance of Class, boolean.class. It
> is an instance not a class, and hence not in a
> package.
>
Makes sense, must be one of the reasons of the confusion.
> > I had a problem. Could not essentially do
> > Class.forName(someClass.getName()) for classes that
> I
> > had obtained through reflection. See my first post
> > for more details why this could have been useful.
>
> Is the map workaround that I suggested sufficient for
> your needs?
I went for the large if-then-else solution.
@RedUnderTheBed
> I haven't read most of the posts before me because [snore], but, >
> Class.forName() returns a Class doesn't it? And you got the parameters
> for that method from a Class object, so why are you bothering with
> Class.forName()?
Because I store the method(s) info in an XML file, which I later on wish to use. See my first post.
> Lastly, all the Class versions of the primitive datatypes have the same
> name but with the first letter capitalised. So couldn't you just capitalise the
> first letter of the returnTypeClass.getName() string?
No necessarily. For char -> Character, int -> Integer.
# 29
> Lastly, all the Class versions of the primitive
> datatypes have the same name but with the first
> letter capitalised. So couldn't you just capitalise
> the first letter of the returnTypeClass.getName()
> string?
except for :
int vs Integer
char vs Character
The Map solution is the way forward
# 30
> > Is the map workaround that I suggested sufficient
> for
> > your needs?
>
> I went for the large if-then-else solution.
In what way is that superior to using a Map?
jverda at 2007-7-29 14:09:57 >

# 31
> > > Is the map workaround that I suggested
> sufficient
> > for
> > > your needs?
> >
> > I went for the large if-then-else solution.
>
> In what way is that superior to using a Map?
I didn't really went over a cost-benefit analysis. Using if-then-else statements is simple enough to implement and using a Map seems like an overkill to me: I only needed a few entries, and at run-time I only search for values never insert new ones.
Finally, (I am not so sure here), isn't an if-then-else search over 8 values faster than using a HashMap for instance? It should be, since a HashMap for every get it calls hash(key.hashCode()); (and several other) before retrieving the key...
# 32
> > > > Is the map workaround that I suggested
> > sufficient
> > > for
> > > > your needs?
> > >
> > > I went for the large if-then-else solution.
> >
> > In what way is that superior to using a Map?
>
> I didn't really went over a cost-benefit analysis.
> Using if-then-else statements is simple enough to
> implement and using a Map seems like an overkill to
> me: I only needed a few entries, and at run-time I
> only search for values never insert new ones.
I say 8 if-else statements is overkill. More actual physical lines of code for one thing, which - don't laugh - is more room for bugs to sneak in. The Map solution is neater
> Finally, (I am not so sure here), isn't an
> if-then-else search over 8 values faster than using a
> HashMap for instance? It should be, since a HashMap
> for every get it calls hash(key.hashCode()); (and
> several other) before retrieving the key...
"Faster" is irrelevant. Forget "performance", it's not an issue. Such micro-optimizations are not worth the bother. I know you really think you need to shave off a few clock cycles here and there, but you don't. The JVM is much smarter at optimizing code than you are. In any case, you're using reflection, which will slow your app down much more than a couple of method calls to a HashMap
# 33
> I didn't really went over a cost-benefit analysis.
> Using if-then-else statements is simple enough to
> implement and using a Map seems like an overkill to
> me: I only needed a few entries, and at run-time I
> only search for values never insert new ones.
I'd say a map much more clearly expresses your intent than a bunch of if/elses. "If it's one of these special names, use the Class object associated with that name, else follow the general rule," is far preferable to "if it's this then that else if it's this then that else if ... else follow the general rule."
It gives you two cases to handle, rather than nine (with eight of them being identical in form).
"To find somebody's number in the phone book, if the last name starts with 'A', open to the 'A' section of the book. If the last name starts with 'B', open to the 'B' section." [and so on C through Y] "...with 'Z', open to the 'Z' section."
vs.
"To find someboy's number in the phone book, open to the section corresponding to the first letter of the last name."
> Finally, (I am not so sure here), isn't an
> if-then-else search over 8 values faster than using a
> HashMap for instance? It should be, since a HashMap
> for every get it calls hash(key.hashCode()); (and
> several other) before retrieving the key...
That difference will be beyond negligible, especially since you're using reflection. Don't make micro-optimizations like that unless and until you've found a performance problem and verified that doing so will improve performance enough to make it worth the fuglination of your code.
jverda at 2007-7-29 14:09:57 >

# 34
Is the map solution really neater? It implies that I need a map variable for my class (although it does not really belong to a class), which I need to instantiate somewhere/ somehow and is only used at a single place! Whereas with the if-then-else statements everything remains localised within a single method, with the disadvantage that the internal of this method is a bit "ugly".
Unless you are suggesting to use an internal class for providing this functionality.
# 35
> Is the map solution really neater? It implies that I
> need a map variable for my class (although it does
> not really belong to a class), which I need to
> instantiate somewhere/ somehow and is only used at a
> single place!
Yes, it is neater. If/else logic of this nature has a habit of bloating over time. Although in this instance, that's only going to happen in the highly unlikely case of a new primitive type being introduced to the language, that's no real reason to avoid the neater solution.
You need not necessarily put this Map in any particular class, make it re-usable. Don't assume the class you're currently working on is the only place you'll ever need to do this. I've got just such a Map in a utility class, in a jar I re-use in whatever project needs it
> Whereas with the if-then-else
> statements everything remains localised within a
> single method, with the disadvantage that the
> internal of this method is a bit "ugly".
It doesn't belong there. It belongs in a utility class
> Unless you are suggesting to use an internal class
> for providing this functionality.
Don't see where you got that from!
# 36
> Is the map solution really neater?
Absolutely.
>It implies that I
> need a map variable for my class (although it does
> not really belong to a class),
Well, you have to put it somewhere. If this class is the only place you'll use it, then yes, it does belong to this class. If you'll use it elsewhere then put it in an appropriate library class.
> which I need to
> instantiate somewhere/ somehow and is only used at a
> single place!
So?
> Whereas with the if-then-else
> statements everything remains localised within a
> single method,
So?
If your class is so big that having a map that's only used in one method makes things confusing, then your class is trying to do too much.
> Unless you are suggesting to use an internal class
> for providing this functionality.
Nope.
Again: The map expresses your intent more clearly. Two cases--special and retrieved from the map or general and generated from the classname. The if/else just repeats the same logic with different data 8 times. Repetition is bad, m'kay.
jverda at 2007-7-29 14:09:58 >

