Kotlin对象表达式要点与Lambda表达式
Kotlin对象表达式要点揭密:
在上一次https://www.cnblogs.com/webor2006/p/11352421.html中学习了Kotlin的对象表达式,它主要是解决Java中匿名内部类的问题,这次继续对它进行学习,在上一次的示例中,我们定义了一个不继承任何类或实现任何接口的对象表达式,回忆如:
当时说该代码看似简单,其实里面有一些很隐晦的东东接下来阐述一下:
嗯,很简单,那接下来改一个东东就会让你觉得难以理解了:
报异常了。。这是为啥呢?这就是之前提出的“隐晦”处了,这里会涉及到对象表达式的一些注意事项及要点,下面来说明一下:
1、匿名对象只能在局部变量范围内或者被private修饰的成员变量范围内才能被识别出来其真正的类型,其中“被识别出真正的类型”的含义是指能正常的调用匿名内部类中的方法或成员变量,比如我们之前定义在局部变量范围的匿名对象:
所以它是能被正常识别出真正类型的,而目前咱们新定义的这个如果是被private修饰的话也是能被识别真正类型:
而如果将private关键字去掉之后,在Kotlin中默认在类中的访问级别就会变为public了,所以该匿名对象是不能被识别出真正的类型的,所以也就如我们所看到的报错了。
2、如果将匿名对象当做一个public方法的返回类型或是public属性的类型,那么该方法或是属性的真正类型就是该匿名对象所声明的父类型,如果没有声明任何父类型,那么其类型就是Any;在这处情况下,匿名对象中所声明的任何成员都是无法访问的。
回到咱们的这个程序理解一下这句话,也就是如果我们当private关键字去掉之后,会变为public属性类型了,此时它真正的类型就是该匿名对象的父类型,而根据“如果没有声明任何父类型,那么其类型就是Any”,也就是说:
为了进一步论证这个理论,咱们可以将myObject的类型打出来:
另外打印类型还有另外一种写法,了解一下:
接下来再来定义一个类进一步再来感受这个对象表达式的注意事项:
我们知道对于Java的匿名内部类中的方法想要访问外层类的变量,该外层类的变量一定得要声明为final才行,但是对于Kotlin的对象表达式而言是没有这个限制的,下面来用程序验证一下:
实际案例:
我们知道在Java的GUI编程中就会用到很多的匿名内部类,因为要监听控件的事件,下面则先用Java原滋原味的展现一下,然后稍后再用Kotlin的对象表达式将其改造,最后再来做一个对比,如下:
package com.kotlin.test3; import javax.swing.*; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; public class JFrameTest { public static void main(String[] args) { JFrame jFrame = new JFrame("My JFrame"); JButton jButton = new JButton("My JButton"); jFrame.addWindowListener(new WindowListener() { @Override public void windowOpened(WindowEvent e) { System.out.println("windowOpened"); } @Override public void windowClosing(WindowEvent e) { System.out.println("windowClosing"); } @Override public void windowClosed(WindowEvent e) { } @Override public void windowIconified(WindowEvent e) { } @Override public void windowDeiconified(WindowEvent e) { } @Override public void windowActivated(WindowEvent e) { System.out.println("windowActivated"); } @Override public void windowDeactivated(WindowEvent e) { } }); jFrame.add(jButton); jFrame.pack(); jFrame.setVisible(true); jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } }
然后运行:
然后咱们可以给Button增加一个点击事件:
还可以将其改为Lambda表达式,如下:
很简单的代码,接下来咱们用Kotlin的方式来实现同样的功能:
好,继续:
好,接下来是来设置可见性,在Java中是这样写的:
而在Kotlin中如果我们敲setVisible会自动匹配其它的一个名称,如下:
会自动变为isVisible,也就是Kotlin中推荐是用属性的方式来代替Java中的set和get方法,如下:
当我们点击查看时,自动会链接到setVisible()方法中:
其中还有一个小细节需要注意,其实在Window中的属性名不是isVisible,而是:
这也就说明了,对于boolean类型的变量,Kotlin会自动将其翻译成is开头的,好程序继续:
接下来给按钮增加点击事件:
Kotlin Lambda表达式:
关于Java的Lambda表达式已经很清楚了,也就是如果对象是Java函数式接口的一个实例(既只拥有一个抽象方法的接口),那么可以通过Lambda表达式来调用,其中Lambda表达式前面加上接口的类型。下面来对上面的Button的点击事件改成Kotlin的Lambda表达式,看跟Java的Lambda表达式有啥不一样:
但是!!其实还可以简化,从上面可以看出“ActionListener”被IDE标灰了,看一下它的提示:
其实这个ActionListener可以由Kotlin的编译推断出来,因为addActionListener方法接收的参数类型就是ActionListener,所以:
最后再来做个小实现: