Skip to content

Add the R generic "toString" to "jobjRef" methods #348

Description

@rikivillalba

This is a feature request:
Sometimes I use to add a method for "jobjRef" to the generic base R toString(x, ...) and map it to java's object toString
It can made possible to use the |> pipe and otherwise save code or prevent the use of reflection for such a basic action as x$toString()

I think in somewhat like:

setMethod("toString", "jobjRef", function(x, ...) .jcall(x, "S", "toString"))

migth work.

Best regards.

Activity

  1. s-u commented on May 16, 2026

    @s-u
    Owner

    Good idea, but I think it may be more R-like to simply use the as.character generic for this instead (which is currently unimplemented) - I'd rather not introduce a new generic unless it is required. That said, there is a slight difference in Java's toString() notion in that as.character is vectorized, so one may think of arrays behaving differently between as.character and toString.

  2. rikivillalba commented on May 17, 2026

    @rikivillalba
    Author

    Yes, as.character seems natural and automatically works with other R functions such as paste.
    On the other hand, R has a generic toString since 1.2 (probably a concept borrowed from Java). The default uses paste to concatenate vectors to a length one output, the manpages describes this single element semantics explicitly:

    This is a helper function for [format] to produce a single character string describing an R object.

    However the default does not use format at all, but as.character through paste coercing of its argument...

    toString(matrix(1:10,2,5))
    # [1] "1, 2, 3, 4, 5, 6, 7, 8, 9, 10"
    

    One may think in separate methods for jarrayRef and jobjRef to obey to the vector nature of as.character:

    setMethod("as.character", "jarrayRef", function(x, ...) {
      r <- as.list(x)    # <- method rJava:::as.list.jarrayRef
      if (!is.recursive(r)) 
        return(as.character(r, ...))
      vapply(r, toString, character(1), ..., USE.NAMES = FALSE)
    })
    
    setMethod("as.character", "jobjRef", function(x, ...) {
      toString(x, ...)
    })
    
    setMethod("toString", "jobjRef", function(x, ...) {
      r<- .jcall(x, "S", "toString")
      toString(r, ...)
    })
    

    However it should be noted that java object arrays (not from primitive types) are more akin of lists, and as.character over lists does not dispatch any generic (not sure)...

    So the results would be:

    # array of objects
    jarray_list <- .jarray(list(
      new(J("java.lang.Integer"), 10L),
      new(J("java.lang.String"), "hello"),
      .jarray(letters[1:3])
    ))
    
    # array of primitive
    jarray_primitive <- .jarray(1:5)
    
    as.character(jarray_list)
    # [1] "10"   "hello"    
    # [3] "[Ljava.lang.String;@2cdf8d8a"
    
    as.character(jarray_primitive)
    # [1] "1" "2" "3" "4" "5"
    

    and r's toString is equivalent to Object.toString.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions