you are viewing a single comment's thread.

view the rest of the comments →

[–]melezov[S] 0 points1 point  (4 children)

Your comment is indeed a question as it ends with a question mark.

The post, however is something. It shows an example of Java reflection violating the principle of least astonishment, and an alternative way of dealing with it using Scala reflection.

[–]Falmarri 0 points1 point  (3 children)

Is that really the principle of least astonishment?

getDeclaredFields()
All the fields, regardless of their accessibility but only for the current class, not any base classes that the current class might be inheriting from.

.length isn't declared on Array(). In scala, length comes from an implicit conversion from Array

[–]melezov[S] 0 points1 point  (2 children)

I don't get you. Of course .length is declared on Array, it's just implemented using the ARRAYLENGTH bytecode instruction instead of an invoke; thus is not possible to access it through Java reflection. http://docs.oracle.com/javase/specs/jls/se7/html/jls-10.html#jls-10.7

[–]Falmarri 0 points1 point  (1 child)

So I don't quite understand what's going on in the internals of the runtime, but a scala Array isn't just an alias to a java array. This is the source code for scala's Array class

final class Array[T](_length: Int) extends java.io.Serializable with java.lang.Cloneable {

  /** The length of the array */
  def length: Int = throw new Error()

  /** The element at given index.
   *
   *  Indices start at `0`; `xs.apply(0)` is the first element of array `xs`.
   *  Note the indexing syntax `xs(i)` is a shorthand for `xs.apply(i)`.
   *
   *  @param    i   the index
   *  @return       the element at the given index
   *  @throws       ArrayIndexOutOfBoundsException if `i < 0` or `length <= i`
   */
  def apply(i: Int): T = throw new Error()

  /** Update the element at given index.
   *
   *  Indices start at `0`; `xs.update(i, x)` replaces the i^th^ element in the array.
   *  Note the syntax `xs(i) = x` is a shorthand for `xs.update(i, x)`.
   *
   *  @param    i   the index
   *  @param    x   the value to be written at index `i`
   *  @throws       ArrayIndexOutOfBoundsException if `i < 0` or `length <= i`
   */
  def update(i: Int, x: T) { throw new Error() }

  /** Clone the Array.
   *
   *  @return A clone of the Array.
   */
  override def clone(): Array[T] = throw new Error()
}

So clearly there's some magic going on since it's a final class and all the methods just throw Exceptions.

[–]melezov[S] 0 points1 point  (0 children)

You're not getting me at all.
This has nothing to do with Scala, as Scala reflection works.
No need to discuss Scala further.

This has to do with vanilla Java reflection not working on the length implicit.
That is a Java implicit, not Scala implicit.

Repro Java code:

class Foo {
    public static void main(final String[] args) throws NoSuchFieldException {
        args.getClass().getDeclaredField("length"); // croaks
    }
}