In Java, we write .class (for example: String.class) to get information about the given class. In Kotlin you can write ::class or ::class.java. What is the difference between them?
By using ::class, you get an instance of KClass. It is Kotlin Reflection API, that can handle Kotlin features like properties, data classes, etc.
By using ::class.java, you get an instance of Class. It is Java Reflection API, that interops with any Java reflection code, but can't work with some Kotlin features.
First you need to understand about Reflection. According to the docs:
Reflection is a set of language and library features that allows for introspecting the structure of your own program at runtime.
In simple words, it gives you the ability to get the code you have written i.e., the class name you have defined, the function name you have defined, etc. Everything you have written, you can access all these at runtime using Reflection.
::class and ::class.java are basic features of Reflection.
::class gives you a KClass<T> reference and ::class.java gives you Class<T> reference.
Example,
val a = MyClass::class
can be interpreted as
val a = KClass<MyClass>()
Note: Above code is not syntactically correct, because KClass is an interface and interfaces cannot be instantiated. It is just to give you an idea.
A Class<T> class gives you information about the metadata of the T class like interfaces it is implementing, its functions' names, its package name, etc.
KClass is similar to Class but it gives information about some more properties(Kotlin related properties) than Class. All the information a KClass<T> reference can give you about the T class are listed here https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect/-k-class/#properties
According to the Kotlin documentation, when we create an object using any class type as below the reference type will be type of KClass.
val c = MyClass::class // reference type of KClass
Kotlin class reference is not the same as a Java class reference. To get a Java class reference, use the .java property on a KClass instance.
val c = MyClass::class.java // reference type of Class Java
Related
I'm trying to generate the runtime class name of a class that is defined in a package object.
Example:
package com.foo
package object bar {
case class MyCaseClass()
}
import bar._
MyCaseClass().getClass.getCanonicalName
The above will generate com.foo.bar.package.MyCaseClass
If I use WeakTypeTag it will correctly generate the type as com.foo.bar.MyCaseClass.
package com.foo
trait MyTrait
case class MyImpl extends MyTrait
def getType[T](t: T)(implicit weakTypeTag WeakTypeTag[T]): String = {
weakTypeTag.tpe.fullName
}
What is the reason for the above difference in behavior? I know I must be missing something about the Scala type system...
This isn't so much about the type system as about the encoding of package objects on the JVM. The JVM doesn't have package-level methods, for example, so the Scala compiler has to create a synthetic class that has static methods, inner classes, etc. corresponding to the definitions in the package object. That class is named package, an arbitrary but self-explanatory name that has the advantage of being a keyword in both Scala and Java, so it's unlikely to result in collisions with non-synthetic code.
Java's reflection APIs know nothing about Scala, so naturally they can't hide this encoding from you. When you call getClass.getCanonicalName you're seeing the actual class name, corresponding to the class file you'd find at com/foo/bar/package\$MyCaseClass.class when you compile your code.
Scala's reflection APIs do know about Scala's encoding of package objects, and they will hide the synthetic package class from you. This arguably makes sense, since the details of the encoding aren't in the spec (if I remember correctly?) and so may vary across platforms or language versions, etc.
The discrepancy is a little confusing, but this isn't the only time you'll run into differences—the Scala reflection API hides lots of mangling, etc. that Java reflection can't.
Several IO interface constructors of the Sodor processor collection implements its own clone method. I looked into the usage of clone method in Scala but still cannot figure out why exactly that is done. (I could not find any explicit usage of these methods anywhere in the design)
Sodor is still currently still on Chisel 2. clone was renamed to cloneType in Chisel 3 to distinguish it from clone in Java and Scala. cloneType is generally required by Chisel in order to instantiate new instances of parameterized Bundles. For example:
class MyBundle extends Bundle {
val foo = UInt(32.W)
}
class MyParameterizedBundle(width: Int) extends Bundle {
val bar = UInt(width.W)
}
Chisel often needs to create an instance of a given Bundle class from another instance of that class. Chisel uses Java reflection to do this. If there are no arguments to the constructor then it can just instantiate the object from the default constructor. However, it cannot determine the value of width from an instance of MyParameterizedBundle via reflection, so it cannot provide an appropriate parameter to the constructor. This is what the cloneType function is for. It tells Chisel how to create a new instance of a Bundle from a given object.
We hope to fix this wart in the future, but have not had the time to implement it. The most promising way is to automatically generate cloneType via Scala macro annotations.
I'm trying to wrap my head around the Scala language and figured the best way to learn is to put it into practice. When copy pasting code between a Java project (Spring) and my Scala project the IDE did a conversion I do not understand. Searching for it on the internet and in the docs gave me nothing to work with unfortunately.
The code:
#Bean private[context] def passwordEncoder: PasswordEncoder = {
return new BCryptPasswordEncoder
}
When compiling the above code the compiler complains:
`error: context is not an enclosing class`
Can anybody explain what the private[context] part means?
context is just a placeholder, where you can fill in the context in which you'd like the method to be private. This is optional though. If you don't specify the context, the member becomes "class-private", which afaik behaves like private does in Java.
Background: Scala offers more than one degree of access specification: the object-private specification, i.e. private[this], stipulates that the member in question can only be seen by members called on that same object, not from different objects, even if they are of the same type. Instead of this you can also use a package name or even root, which is an alias for the root namespace.
More information on this can be found in "Section 5.2 - Modifiers" of the Scala Language Reference:
The private modifier can be used with any definition or declaration in a template.
[...]
The modifier can be qualified with an identifier C (e.g. private[C]) that must denote a class or package enclosing the definition. Members labeled with such a modifier are accessible respectively only from code inside the package C or only from code inside the class C and its companion module (§5.4).
I want to understand class files and inner/nested classes a bit better and I'm wondering about the following things:
Is the InnerClasses attribute used to refer tothe inner/nested classes in the ´containing´ class or is it used in the inner/nested classes to refer to the ‘container’ class?
Is the InnerClasses attribute in class files sufficient? E.g. Do inner/nested classes have to follow the name mangling with $ or is this just a convention?
Is there a way to make a class look like an inner/nested class to the JVM without setting the InnerClasses attribute and does this depend on the JLM vendor? (I remember hearing that IBM's implementation had less strict requirements in some parts.)
How much does the class loading mechanism of the JVM interact with Java reflection? Would it be possible to make the JVM disagree with the results from Java reflection?
I tried looking it up in the JVM specification but didn't find a description of the actual mechanism.
I only found this sentence in “The InnerClasses Attribute” remotely connected to my question:
The Java virtual machine does not currently check the consistency of
the InnerClasses attribute with any class file actually representing a
class or interface referenced by the attribute.
A few additions to the previous answer:
Is the InnerClasses attribute used to store the contained inner/nested classes in the containing class or is it used in the inner/nested classes to refer to the ‘container’ class?
The bytecode of every compiled class is stored in a separate .class file. The the actual "inner classes" are not stored in that attribute. As the previous post pointed out, that attribute only points to classes that the compiler knew about when creating the bytecode.
Is the InnerClasses attribute in class files sufficient? E.g. Do inner/nested classes have to follow the name mangling with $ or is this just a convention?
Is there a way to make a class look like an inner/nested class to the JVM without setting the InnerClasses attribute and does this depend on the JLM vendor? (I remember hearing that IBM's implementation had less strict requirements in some parts.)
For both questions, I am not certain. But I think the concept of inner/nested classes is something that the Java language (and hence the Java compiler provides). In the bytecode, there should not be any difference between a class that was declared as a normal public class and some nested or inner class.
You could easily try out how an given VM handles this like so:
Create a class with some nested and inner classes
Write a little program that tries to load and instantiate one of the inner classes through reflection from outside the scope of defining class. You must use reflection here, because the Java compiler will not allow you to instantiate a nested class that is not in scope! If you can successfully instantiate the class, that is evidence that internally the VM does not handle nested and normal classes differently.
How much does the class loading mechanism of the JVM interact with Java reflection? Would it be possible to make the JVM disagree with the results from Java reflection?
I don't understand this last question. Could you explain a bit more what you mean when you say the VM and reflection should disagree?
I know that there is an inner class attribute in class files, but is this sufficient?
The InnerClasses attribute is in the byte code and it lists all the known inner classes of the outer class. This is not something you can use directly.
E.g. Do inner/nested classes have to follow the name mangling with $ or is this just a convention?
The compiler will follow this convention and you have no control over it.
Is there a way to make a class look like an inner/nested class to the JVM without setting the inner class attribute and does this depend on the JLM vendor? (I remember hearing that IBM's implementation had less strict requirements in some parts.)
You can create a class with the same name. YOu cna try that for yourself.
How much does the class loading mechanism of the JVM interact with Java reflection?
I don't believe the class loader uses reflection. However reflection may get its information from the same place the class loader does. I don't see why it would matter.
Would it be possible to make the JVM disagree with the results from Java reflection?
You can use reflection to corrupt the data in reflection based objects. Again, not sure why you would want to do this.
I've written a Scala trait, named Cache[A,B], to provide a caching API. The Cache has the following methods, asyncGet(), asyncPut(), asyncPutIfAbsent(), asyncRemove().
I'm going to have a few static methods, such as getOrElseUpdate(key: A)(op: => B). I don't want methods like this as abstract defs in the Cache trait because I don't want each Cache implementation to have to provide an implementation for it, when it can be written once using the async*() methods.
In looking at Google Guava and parts of the Java library, they place public static functions in a class that is the plural of the interface name, so "Caches" would be the name I would use.
I like this naming scheme actually, even though I could use a Cache companion object. In looking at much of my code, many of my companion objects contain private val's or def's, so users of my API then need to look through the companion object to see what they can use from there, or anything for that matter.
By having a object named "Caches" is consistent with Java and also makes it clear that there's only public functions in there. I'm leaning towards using "object Caches" instead of "object Cache".
So what do people think?
Scala's traits are not just a different name for Java's interfaces. They may have concrete (implemented) members, both values (val and var) and methods. So if there's a unified / generalized / shared implementation of a method, it can be placed in a trait and need not be replicated or factored into a separate class.
I think the mistake starts with "going to have a few static methods". Why have static methods? If you explain why you need static methods, it will help figure out what the design should be.