calvin
calvin

Reputation: 2975

How can I get companion object from a class name?

I have some spark model files and I want to load them. One way is to write the following codes.

LogisticRegressionModel.load(path)

However, I need to have a model object so that I call LogisticRegressionModel.load. I only get class name like org.apache.spark.ml.classification.LogisticRegressionModel, so I need to reflect companion object from class name, but how can I do this?

From this post, I find there is a maybe broken way. But when I tried, I find no companion field in classMirror.

Upvotes: 1

Views: 396

Answers (1)

Mateusz Kubuszok
Mateusz Kubuszok

Reputation: 27595

If you know a type in compile time, you can try using slightly newer API that works in 2020:

import scala.reflect.runtime.universe._

def findCompanionOf[T: TypeTag] =
  runtimeMirror(getClass.getClassLoader)
    .reflectModule(typeOf[T].typeSymbol.companionSymbol.asModule)
    .instance
@ findCompanionOf[Long]
res15: Any = object scala.Long

If you know only name as a String or as Class[_]... then if companion exists it's .class name + $, while the instance should be available in static field MODULE$.

def findCompanionOf(clazz: Class[_]) =
  clazz.getClassLoader
    .loadClass(classOf[List[_]].getName + "$")
    .getField("MODULE$")
    .get(null) // obtaining static field = obtaining value for null instance
@ findCompanionOf(classOf[List[_]])
res25: Class[?0] = class scala.collection.immutable.List$

In both cases if class/type doesn't have an companion then code with throw, though the second version also won't work with primitives like Long, Int, etc.

In your case something like:

findCompanionOf(
  getClass.getClassLoader.loadClass("org.apache.spark.ml.classification.LogisticRegressionModel")
)

might work.

Upvotes: 3

Related Questions