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 > top of Java-index,Core,Core APIs...
# 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 > top of Java-index,Core,Core APIs...
# 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.

georgemca at 2007-7-29 14:09:48 > top of Java-index,Core,Core APIs...
# 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 > top of Java-index,Core,Core APIs...
# 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

georgemca at 2007-7-29 14:09:48 > top of Java-index,Core,Core APIs...
# 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 > top of Java-index,Core,Core APIs...
# 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!

georgemca at 2007-7-29 14:09:48 > top of Java-index,Core,Core APIs...
# 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 > top of Java-index,Core,Core APIs...
# 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...

oeberta at 2007-7-29 14:09:48 > top of Java-index,Core,Core APIs...
# 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.

ntalamaia at 2007-7-29 14:09:48 > top of Java-index,Core,Core APIs...
# 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.

georgemca at 2007-7-29 14:09:48 > top of Java-index,Core,Core APIs...
# 12

I still don't see any paradox.

jverda at 2007-7-29 14:09:48 > top of Java-index,Core,Core APIs...
# 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 > top of Java-index,Core,Core APIs...
# 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.

oeberta at 2007-7-29 14:09:48 > top of Java-index,Core,Core APIs...
# 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

georgemca at 2007-7-29 14:09:53 > top of Java-index,Core,Core APIs...
# 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) ...

oeberta at 2007-7-29 14:09:53 > top of Java-index,Core,Core APIs...
# 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

georgemca at 2007-7-29 14:09:53 > top of Java-index,Core,Core APIs...
# 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.

ntalamaia at 2007-7-29 14:09:53 > top of Java-index,Core,Core APIs...
# 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?

georgemca at 2007-7-29 14:09:53 > top of Java-index,Core,Core APIs...
# 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.

ntalamaia at 2007-7-29 14:09:53 > top of Java-index,Core,Core APIs...
# 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

georgemca at 2007-7-29 14:09:53 > top of Java-index,Core,Core APIs...
# 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)

oeberta at 2007-7-29 14:09:53 > top of Java-index,Core,Core APIs...
# 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?

georgemca at 2007-7-29 14:09:53 > top of Java-index,Core,Core APIs...
# 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.

oeberta at 2007-7-29 14:09:53 > top of Java-index,Core,Core APIs...
# 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

georgemca at 2007-7-29 14:09:53 > top of Java-index,Core,Core APIs...
# 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 > top of Java-index,Core,Core APIs...
# 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?

RedUnderTheBeda at 2007-7-29 14:09:53 > top of Java-index,Core,Core APIs...
# 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.

ntalamaia at 2007-7-29 14:09:53 > top of Java-index,Core,Core APIs...
# 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

georgemca at 2007-7-29 14:09:53 > top of Java-index,Core,Core APIs...
# 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 > top of Java-index,Core,Core APIs...
# 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...

ntalamaia at 2007-7-29 14:09:57 > top of Java-index,Core,Core APIs...
# 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

georgemca at 2007-7-29 14:09:57 > top of Java-index,Core,Core APIs...
# 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 > top of Java-index,Core,Core APIs...
# 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.

ntalamaia at 2007-7-29 14:09:57 > top of Java-index,Core,Core APIs...
# 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!

georgemca at 2007-7-29 14:09:57 > top of Java-index,Core,Core APIs...
# 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 > top of Java-index,Core,Core APIs...