On 26/06/2021 17:41, Peter Levart wrote:
What I'm asking is this: why couldn't the following always hold (local vars):

Foo.val v = ...
Foo.ref r = ...

assert v.getClass() == Foo.val.class;
assert r.getClass() == Foo.ref.class;


I knew this was a stupid question. Immediately after considering:

Object vo = v;
Object ro = r;

assert vo.getClass() == ???;
assert ro.getClass() == ???;


...I realized that the primitive class type (val vs. ref) is not a property of the object, but rather the property of how its value is passed around and stored by VM. Since .getClass() can only return something that characterizes the object and not how its value is stored or passed, the primitive class type (through Q or L descriptors) is more a property of a field or array element or method parameter or method return as Gernot Nappert said in his reply:


On 24/06/2021 09:16, Gernot Neppert wrote:
I'm reading your various proposals to reconcile descriptors with type-mirrors, and they all seem to have their awkward corner-cases.

Granted, we have "Q-type" descriptor vs. "L-type" descriptors for class members, method argumens and method return-types, and we need to make this disctinction visible *somehow* via reflection.

But: do we really need to have two different type-mirrors corresponding to these descriptors? Isn't the "Q-ness" rather a property of the Field, method Parameter or method return-type, and therefore should be available there via reflection as a simple boolean property?

Given a value-favoring class "Point" and the following declaration:

public class Foo {

    Point.ref pt;

   public void setPoint(Point p) {
        this.pt = pt;

    }

    public Point.ref getPoint() {
        return pt;
    }
}

Extending the reflection API for the corresponding classes from java.lang.reflect would look something like this:

assertFalse(Point.class.getDeclaredField("pt").isByValue());

assertTrue(Point.class.getMethod("setPoint", Point.class).getParameters()[0].isByValue());

assertFalse(Point.class.getMethod("getPoint").getParameters()[0].isReturnByValue());



Extending reflection API in this way could work for querying the properties of fields, methods and constructors, but there are also those "find me a method / constructor with specific parameter types" reflection methods:

Class.get(Declared)Method(String name, Class<?>... parameterTypes)
Class.get(Declared)Constructor(Class<?>... parameterTypes)

It would be possible, but awkward to add methods like:

Class.get(Declared)Method(String name, Class<?>[] parameterTypes, boolean[] parameterByValue)


Seems like we are forced to re-use Class objects to hold this additional info. Remi says that there should only be "primary" (ref type) primitive class literals (Foo.class) and no (Foo.ref.class or Foo.val.class) and that val type mirrors should be obtained by calling a method (such as Foo.class.asPrimitiveValType()), but that makes methods/constructors using val-typed parameters second class citizens when using reflection. There's nothing wrong with Foo.ref.class and Foo.val.class per-se. It seems the question is more whether we actually need type mirrors for val-types and not how to obtain them (Foo.val.class is surely nicer than Foo.class.asPrimitiveValType() and not a bit less expressive).

We already have two kinds of primitive class type mirrors since primitive types are going to be retro-fitted as primitive classes (int.class vs. Integer.class). So today, when you say:

Math.class.getMethod("min", Integer.class, Integer.class)

...you get "NoSuchMethodException", so there's no fuzziness in matching the parameter types. You have to use the correct type mirrors:

Math.class.getMethod("min", int.class, int.class)


So I thing introducing fuzziness for primitive class parameter types except for retrofitted primitive types would just make things more irregular.

I also think what Brian proposed (Foo.class is aligned with .getClass()) is pretty consistent when you think about it long enough.


Regards, Peter


Reply via email to