2

I'm using Xtend to write an Android app, and I wanted to use the elvis operator to simplify the following (which works):

val c = if (projection != null) new MatrixCursor(projection) else new MatrixCursor(#[MediaStore$MediaColumns::DISPLAY_NAME, MediaStore$MediaColumns::SIZE])

By using elvis operator, I wrote:

val c = new MatrixCursor(projection ?: #[MediaStore$MediaColumns::DISPLAY_NAME, MediaStore$MediaColumns::SIZE])

which, as far as I understand, works in the same way.

However, I got this error in Eclipse: Type mismatch: cannot convert from Object to String[] What's wrong with it?

I'm using Xtend 2.4, the MatrixCursor constructor signature is MatrixCursor(String[]), and projection is defined explicitly as String[].

Randy Sugianto 'Yuku'
  • 71,383
  • 57
  • 178
  • 228

1 Answers1

3

You are stumbling across a limitation of the type inference. The elvis operator is defined as something along these lines:

def <T> T elvis(T original, T placeholder) {
  ..
}

If order to bind the type variable T, both operand types are computed. Since the array literal #[..] is actually primarily a list literal, the binding for T is computed from String[] and List<String> rather than two String[]. Therefore the common supertype is Object so elvis is just an Object. You can convince the type system, that you want the second operand to be a String[] by explicitly casting it:

val c = new MatrixCursor(projection ?: #[DISPLAY_NAME, SIZE] as String[])
Sebastian Zarnekow
  • 6,609
  • 20
  • 23