Kotlin(十三)之Kotlin调用java

权烨磊
2023-12-01

属性

  1. Kotlin调用属性本质就是调用getter和setter方法,因此只要java提供setter、getter方法,kotlin就可以直接读取或者写入
  2. 如果getter方法的返回值类型是boolean,并且该getter方法名以is开头,此时Kotlin会将其当作属性名与getter方法同名的属性,比如boolean isFlag 可以作为Kotlin的只读属性,该属性名为isFlag

方法

  1. 如果java方法的返回值是void,在Kotlin中对应于Unit返回值类型。如果有人使用其返回值,它将由 Kotlin 编译器在调用处赋值, 因为该值本身是预先知道的(是 Unit)。

  2. Kotlin的关键字比java多,很多关键字在java中并不是关键字,所以可能出现java的类、接口名、方法名是Kotlin关键字的情况,此时需要加反引号对关键字进行转译

    java类
    public class User {
        private String userName;
        private boolean isMarried;
        protected int age;
    
        public void in() {
            System.out.println("in run...");
        }
        public String getUserName() {
            return userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
        }
    
        public boolean isMarried() {
            return isMarried;
        }
    
        public void setMarried(boolean married) {
            isMarried = married;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    
    kotlin中调用
    fun main(args: Array<String>) {
        val user = User()
        user.userName = "jannal"
        user.isMarried = true
        println(user.userName)
        println(user.isMarried)
        //in在kotlin中是关键字,所以在kotlin中需要调用in()需要转译(``)
        user.`in`();
    }
    

类型

  1. Kotlin为java部分类提供了一些处理,这部分java类被映射为Kotlin类,这种映射只在编译阶段发生,运行时还是java类型。这些 Java 类型的静态成员不能在相应 Kotlin 类型的伴生对象中直接访问。要调用它们,请使用 Java 类型的完整限定名,例如 java.lang.Integer.toHexString(foo)

  2. Java 的原生类型映射到相应的 Kotlin 类型

Java 类型Kotlin 类型
bytekotlin.Byte
shortkotlin.Short
intkotlin.Int
longkotlin.Long
charkotlin.Char
floatkotlin.Float
doublekotlin.Double
booleankotlin.Boolean
  1. Java 的装箱原始类型映射到可空的 Kotlin 类型。用作类型参数的装箱原始类型映射到平台类型, 例如,List<java.lang.Integer> 在 Kotlin 中会成为 List<Int!>

    Java 类型Kotlin 类型
    java.lang.Bytekotlin.Byte?
    java.lang.Shortkotlin.Short?
    java.lang.Integerkotlin.Int?
    java.lang.Longkotlin.Long?
    java.lang.Characterkotlin.Char?
    java.lang.Floatkotlin.Float?
    java.lang.Doublekotlin.Double?
    java.lang.Booleankotlin.Boolean?
  2. 非原生的内置类型

    java.lang.Objectkotlin.Any!
    java.lang.Cloneablekotlin.Cloneable!
    java.lang.Comparablekotlin.Comparable!
    java.lang.Enumkotlin.Enum!
    java.lang.Annotationkotlin.Annotation!
    java.lang.CharSequencekotlin.CharSequence!
    java.lang.Stringkotlin.String!
    java.lang.Numberkotlin.Number!
    java.lang.Throwablekotlin.Throwable!
  3. 集合类型:集合类型在 Kotlin 中可以是只读的或可变的

    Java 类型Kotlin 只读类型Kotlin 可变类型加载的平台类型
    Iterator<T>Iterator<T>MutableIterator<T>(Mutable)Iterator<T>!
    Iterable<T>Iterable<T>MutableIterable<T>(Mutable)Iterable<T>!
    Collection<T>Collection<T>MutableCollection<T>(Mutable)Collection<T>!
    Set<T>Set<T>MutableSet<T>(Mutable)Set<T>!
    List<T>List<T>MutableList<T>(Mutable)List<T>!
    ListIterator<T>ListIterator<T>MutableListIterator<T>(Mutable)ListIterator<T>!
    Map<K, V>Map<K, V>MutableMap<K, V>(Mutable)Map<K, V>!
    Map.Entry<K, V>Map.Entry<K, V>MutableMap.MutableEntry<K,V>(Mutable)Map.(Mutable)Entry<K, V>!
  4. 数组类型映射,kotlin的数组是不型变的,即Array不能赋值给Array,这与java是不同的,java的String[]可以直接赋值给Obejct[]变量,但是java这种方式很容易导致异常。

    Java 类型Kotlin 类型
    int[]kotlin.IntArray!
    String[]kotlin.Array<(out) String>!
  5. 泛型转换

    Java 类型Kotlin 类型
    Foo<? extends Bar>Foo<out Bar!>!
    Foo<? super Bar>Foo<in Bar!>!
    Foo<*>Foo<out Any?>!
    FooFoo<*>
  6. kotlin与java一样泛型都会在编译后擦除,即运行时无法保留泛型信息,所以kotlin中使用is进行类型检测时只能检测星号

    val list = listOf<Int?>(1,2,3)
    // list is List<Int>
    list is List<*>
    

可变参数

  1. 对于可变参数,java中可以直接传入一个数组,但是kotlin不行。kotlin要求只能传入多个参数值,但也可通过使用**"*"**解开数组的方式来传入多个数组元素作为参数值

    java代码
    public class JavaVarargs {
        public void info(int... nums) {
            for (int i = 0; i < nums.length; i++) {
                System.out.println(nums[i]);
            }
        }
    }
    
    kotlin代码
    fun main() {
        var jv = JavaVarargs()
        jv.info(2, 3, 4)
    
        var intArr = intArrayOf(2, 3, 4)
        jv.info(*intArr)
    }
    

异常

  1. Kotlin没有checked异常,对于java可能引发checked异常的方法、构造器,kotlin不会强制要求捕获异常

Object

  1. java的java.lang.Object对应Kotlin的Any,因为Any只有toString()、hashcode()、equals(),所以需要考虑Object有但是Any没有的方法

  2. 如果程序中需要调用wait()/notify()/notifyAll(),可以在程序中将Any强制转换为Object

    (foo as java.lang.Object).wait()
    
  3. getClass (),在kotlin通过如下方式

    obj::class.java
    obj.javaClass
    
  4. clone(),在kotlin中实现kotlin.Cloneable接口即可

  5. finalize(),在kotlin直接写此方法,不需要override关键字(因为Any中没有此方法),finalize不能定义为private

    class Foo{
      protected fun finalize(){
      
      }
    
    }
    

静态

  1. 访问静态成员,kotlin通过伴生对象的语法来访问

    java代码
    public class User {
        public static final String STATUS = "1";
        public static void info(){
            System.out.println("静态方法info");
        }
    }    
    
    
    kotlin代码
    fun main(args: Array<String>) {
        User.info()
        User.STATUS
    }
    
    

SAM转换

  1. java8支持使用Lambda表达式来作为函数式接口的实例(这种机制称为SAM转换),SAM 是Single Abstract Method是缩写,SAM转换的条件:Java的接口,只有一个接口当参数的方法,可以使用lambda当参数

    java代码
    public class SAMInJava {
        private ArrayList<Runnable> runnables = new ArrayList<Runnable>();
    
        public void addTask(Runnable runnable) {
            runnables.add(runnable);
            System.out.println("添加:" + runnable + "任务之后,一共有" + runnables.size() + "个任务");
        }
    
        public void removeTask(Runnable runnable) {
            runnables.remove(runnable);
            System.out.println("删除:" + runnable + "任务之后,一共有" + runnables.size() + "个任务");
        }
    }
    
    kotlin代码
    /**
     * kotlin本身不支持将只有runnable接口当参数的方法直接以lambda方式使用,
     * 但使用typealias关键词给Runnable起别名之后(相当于() -> Unit就是Runnable),
     * 就可以以lambda方式使用
     */
    typealias Runnable = () -> Unit
    
    class SAMInKotlin {
        fun addTask(runnable: Runnable) {
    
        }
    }
    
  2. kotlin调用java代码

    /**
     * kotlin与java互操作(SAM 转换)
     * 1.对于实现了kotlin实现的java接口,在java函数中定义该参数后,kotlin引用时可以用lambda表达式使用
     * 2.由于java与kotlin表达式并不兼容,所以在每次添加lambda表达式都不是同一个对象
     */
    fun main(args: Array<String>) {
        val samInJava = SAMInJava() //实例化java中的类
    
        //lambda调用方法1:使用java中的带kotlin已支持的接口参数的方法,可以直接使用lambda表达式当参数
        samInJava.addTask {
            println("Hello")
        }
    
        val lambda = {
            println("World")
        }
    
        //lambda调用方法2
        samInJava.addTask(lambda)
        samInJava.addTask(lambda)
        samInJava.addTask(lambda)
        samInJava.addTask(lambda)
    
        samInJava.removeTask(lambda)
        samInJava.removeTask(lambda)
        samInJava.removeTask(lambda)
        samInJava.removeTask(lambda)
    
        val samInKotlin = SAMInKotlin() //实例化kotlin中的类
        //以lambda表达式使用kotlin中的方法
        samInKotlin.addTask {
            println("haha")
        }
    }
    

JNI

  1. 在java中使用JNI,需要使用native方法,表示该方法将会交给平台本地代码实现

  2. 在kotlin中使用external,函数不能有函数体

    external fun foo(x: Int):Double
    
 类似资料: