103

I'm new to Kotlin
I used this code for opening another activity:

startActivity(Intent(this,IntroAndLang::class.java))

current activity and target activity are written in Kotlin

I can't understand why there is not single : instead of :: at IntroAndLang::class.java

Winner1
  • 1,261
  • 2
  • 12
  • 17
  • 4
    : is for declaration, :: is an operator. See [here](https://kotlinlang.org/docs/reference/reflection.html). – m0skit0 Nov 20 '17 at 21:02
  • 1
    @m0skit0 thanks,why its class.java when I'm using a kotlin class? – Winner1 Nov 20 '17 at 21:03
  • 12
    Android API only accepts Java classes, that's why you need to pass a Java class. `IntroAndLang::class` returns a `KClass` (a Kotlin class), then `.java` returns the Java class. Note that all Kotlin classes are compiled to Java classes (`.class` binaries) in the end. – m0skit0 Nov 20 '17 at 21:04

4 Answers4

121

:: is used for Reflection in kotlin

  1. Class Reference val myClass = MyClass::class
  2. Function Reference this::isEmpty
  3. Property Reference ::someVal.isInitialized
  4. Constructor Reference ::MyClass

For detailed reading Official Documentation

lmiguelvargasf
  • 63,191
  • 45
  • 217
  • 228
Rahul
  • 4,699
  • 5
  • 26
  • 38
110

:: converts a Kotlin function into a lambda.

Let's say you have a function that looks like this:

fun printSquare(a: Int) = println(a * 2)

And you have a class that takes a lambda as a 2nd argument:

class MyClass(var someOtherVar: Any, var printSquare: (Int) -> Unit) {
        
    fun doTheSquare(i: Int) {
        printSquare(i)
    }
}

How do you pass the printSquare function into MyClass? If you try the following, it wont work:

  MyClass("someObject", printSquare) //printSquare is not a LAMBDA, it's a function so it gives compile error of wrong argument

So how do we CONVERT printSquare into a lambda so we can pass it around? Use the :: notation.

MyClass("someObject",::printSquare) //now compiler does not complain since it's expecting a lambda and we have indeed converted the `printSquare` FUNCTION into a LAMBDA. 

Also, please note that this is implied... meaning this::printSquare is the same as ::printSquare. So if the printSquare function was in another class, like a Presenter, then you could convert it to lambda like this:

Presenter::printSquare

UPDATE:

Also this works with constructors. If you want to create the constructor of a class and then convert it to a lambda, it is done like this:

(x, y) -> MyClass::new

this translates to MyClass(x, y) in Kotlin.

JohnyTex
  • 3,323
  • 5
  • 29
  • 52
j2emanue
  • 60,549
  • 65
  • 286
  • 456
  • are you sure `MyObject::new` still works? I get an error when including it in source code as an expression. – user2297550 Nov 03 '21 at 19:49
  • 2
    I don't quite agree with the wording of this answer, as in the context of programming languages "lambda" (usually) refers to _anonymous_ function. On the other hand, the `::` operator (in this context) creates a _callable reference_ to a function, i.e. a name that can be used to call said function later in the code. – A.P. Jan 14 '22 at 10:40
51

As stated in the docs this is a class reference:

Class References: The most basic reflection feature is getting the runtime reference to a Kotlin class. To obtain the reference to a statically known Kotlin class, you can use the class literal syntax:

val c = MyClass::class
//The reference is a value of type KClass.

Note that a Kotlin class reference is not the same as a Java class reference. To obtain a Java class reference, use the .java property on a KClass instance.

It’s also the syntax for method references as in this simple example:

list.forEach(::println)

It refers to println defined in Kotlin Standard library.

s1m0nw1
  • 76,759
  • 17
  • 167
  • 196
  • 5
    `::println` and `IntroAndLang::class` are unrelated despite both using `::`. Method reference couldn't evaluate to a `KClass`, it isn't a SAM type! – Alexey Romanov Nov 21 '17 at 06:36
  • You’re right that was not the cleanest answer, I modified it – s1m0nw1 Nov 21 '17 at 06:42
  • :: is just a way to write a lambda expression basically we can use this to refer to a method i.e a member function or property for example ```class Person (val name: String, val age: Int)``` Now we can write this to access the person which has the maximium age. ```people.maxBy{it.age}``` we can modify the above to ```people.maxBy(Person::age)``` – pcsaunak Oct 06 '20 at 10:32
3

Since kotlin 1.1, in addition to class, function, property and constructor references as stated above, '::' can also be used to obtain the bound references to all of the above.

For instance, using '::class' could be used to get the exact class of a particular object despite the type of the receiver as below...

val widget: Widget = ...
assert(widget is GoodWidget) { "Bad widget: ${widget::class.qualifiedName}" }

widget::class returns the exact class of the object 'widget' as either 'GoodWidget' or 'BadWidget' despite the type of the receiver expression (i.e 'Widget' as declared initially)

More info at https://kotlinlang.org/docs/reference/reflection.html

Oluwasegun Wahaab
  • 2,663
  • 3
  • 16
  • 19