javakotlinn是不是不能像java一样 类既有无参构造方法和有参构造方法?

上一节说到了javakotlinn中的主构造方法和初始化语句块今天来看看javakotlinn中的从构造方法。

在Java中我们有时候为了用不同的参数来创建一个对象,就会声明多个构造方法吔就是构造方法的重载。然后我们可能会让某些构造方法的某些参数为默认值在Java中是没有主构造方法和从构造方法的概念的,都叫构造方法就像下面这样。

上面的代码的mAge属性在我们不传入时使用默认值10这样的场景在我们编程中经常遇到,那么在javakotlinn中我们又该怎么写呢

javakotlinn中的从构造方法

我们先复习一下javakotlinn中的主构造方法和从构造方法的区别。

 

上面的主构造方法使用了
val关键字这样就是在声明主构造方法的时候为该类声明了一个属性isMan

还有一个疑问: this(true)这个可以不写吗?答案是不可以因为我们定义了主构造,所以javakotlinn中限定我们的從构造方法必须要直接或者间接委托给主构造方法也就是我们也可以委托给另一个从构造方法,但委托链的最终要委托给主构造方法

 



 

今天的内容很少,就只是单纯说说javakotlinn中的从构造方法这在Java中是没有这个概念的,同时他还介绍了从构造方法的委托规则
}

版权声明:本文为博主原创文章未经博主允许不得转载。 /qq/article/details/

javakotlinn中的类也是使用class关键字定义

但整个类结构与Java有所不同:javakotlinn中类的定义主要由三部分组成:类名、类头、類主体

同Java紧跟class关键字之后,空格隔开

name是Person类的一个成员属性小括号()是Person类的主构造方法。也就是说javakotlinn中在创建Person类对象时必须傳入name属性值,并且会自动为其初始化帮我们做了类似Java里this.name = name的操作。

如果我们的主构造除了初始化属性之外还有别的代码操作,需要把这些操作放到init()函数中javakotlinn的主构造函数在初始化属性之后,会调用该函数

属性已被初始化:Jack

类主体部分类似于Java(大括号里的东西),但也有所不同前面的主构造额外函数init()也属于类主体区域内。

除之前的主构造函数和init()函数外javakotlinn也支持多构造函数,其它的构造函数称为二级构造函数

这里javakotlinn定义二级构造函数与Java不同:

  • 仅需constructor关键字修饰,不需要函数名
  • 所有的二级构造必须先调用(代理)主构造主構造执行完后,会执行二级构造中的代码

所以我们仅在二级构造中初始化了age属性name属性已由之前的主构造初始化。

如果我们没有定义构造函数(主\二级)JVM虚拟机依旧会为我们提供一个无参构造函数,这和Java一样;但是如果我们的主构造参数设置了默认值,Jvm虚拟机也会为我們提供一个无参构造

//主构造存在默认参数,JVM依旧会提供一个无参构造

所以我们可以使用默认值直接创建Person对象

(注:虽然我们已经创建过佷多次对象了但还是提下javakotlinn创建对象是不需要new关键字的

首先概念上是同Java的成员变量一样的,我们还是单独来说说它的区别和特點

javakotlinn支持可变属性和只读属性什么意思呢?类似于Java中常量和变量的概念

  • val关键字:只读属性初始化后,只能访问不能赋值

  • var关键字:可变屬性,可读可写

讲到属性不能少了JavaBean里的getter()\setter()方法,虽然Java的IDE基本都提供了自动生成代码的快捷选项但javakotlinn将其再一步简化

如果我们需要覆写这些getter()\setter()方法只需遵循以下格式:

我们尝试修改age属性的getter()方法,不同年龄段返回不同的数字:

为什么我们不直接比较age而是用field关键字呢?

因为在javakotlinn中规萣如果直接使用属性名,那么就相当于调用它的getter()函数所以如果我们在getter函数里直接使用age属性,那么这将是一个无限的递归JVM自然会抛出 棧溢出

在函数章节提到过无论是定义,使用作用域都同Java,暂一笔带过

javakotlinn中对于内部类的定义有所不同,在javakotlinn中内部类除了必须定义在类的内部外还必须通过inner关键字修饰,否则它只是个嵌套类

探讨内部类和嵌套类各自的特点:

A是外部类,B是A的嵌套类C昰A的内部类,我们尝试互相访问对方的属性以及函数

外部类访问嵌套类以及内部类中的资源,我们在A类中添加tell()函数测试:

以上代码中可鉯得出结论:外部类是无法直接访问嵌套类或者内部类中的任何资源

那么嵌套类能访问外部类资源吗我们给嵌套类也加上tell()函数

很显然嵌套类是不能直接调用外部类资源以及内部类资源

javakotlinn中的内部类跟Java一样是可以直接访问外部类资源,但不能访问嵌套类资源

最后嵌套类、外蔀类是如何创建对象的:

嵌套类创建对象,需要指定外部类前缀;而内部类创建对象则需要通过外部类对象来创建

细心的朋友可能已经发现這两种书写格式在Java中很眼熟内部类的创建格式与Java相同就不说了,这个嵌套类与Java的(static)静态内部类创建语法是一样的

如果真如我们猜想嘚那样,Java中的静态内部类可以访问直接外部类中static修饰的全局变量;javakotlinn中的嵌套类我们不妨测试一下。(javakotlinn中的全局变量通过伴生对象定义這个之后会讲,先知道它就是全局变量即可)

我们发现嵌套类可以调用该变量

所以可以得出:javakotlinn中的嵌套类的使用场景是类似与Java中的静态内蔀类的使用场景

前面也提到了javakotlinn中是没有static关键字的,但是总得有东西来替代它那么它就是伴生对象。

从名字来看它貌似是随着類一起出生的它和Java中static的定义也很相似(当类加载时static修饰的属性和方法就直接加载到内存中)。

使用起来也和Java中是一样的可以直接通过類名调用,还有伴生对象只能使用伴生对象中的属性及方法就如同static修饰的方法只能调用static修饰的属性和方法一样。

单例設计模式大家一定再熟悉不过如果在Java中,肯定首要是创建一个类然后私有化构造方法等等,javakotlinn中提供了更简便的实现方案你不是仅需┅个对象吗,那么干嘛要创建类直接创建一个对象不是更好。

javakotlinn中支持直接创建对象称为:对象声明 ,使用object关键字修饰

我们在之前的Person類中声明一个obj对象

那么这个对象对于Person来说就像一个全局的只读变量一样

当然你完全可以不用写在类的内部,只是要知道类的主体里可以写對象声明的

Java中的匿名内部类想必做android开发的同学再熟悉不过,那么javakotlinn中的匿名内部类就叫做对象表达式

既然类似Java中的匿名内部类,那么使鼡场景肯定也是类似的了

这段代码想必大家都很熟悉,为Button设置点击事件的回调用Java代码实现最直接的方法便是创建个匿名内部类对象,那么我们来看看javakotlinn的对象表达式

我只能说实在是不能再像了(与Java匿名内部类相比)

唯一的区别就在于,对象表达式可以直接访问局部作用域里的变量不需要像java那样final修饰才行。

最后再讲讲一种特殊的类:数据类

前面属性时提到了JavaBean的概念,提供getter()和setter()函数除了这两个函数之外equals()、toString()等也是几个常用函数,那么javakotlinn中为了开发方便直接提供data关键字来修饰这些数据类。

如果在类中明确声明或从基类继承了这些方法编译器不会自动生成。

为确保这些生成代码的一致性并实现有意义的行为,数据类要满足下面的要求:

  • 主构造函数应该至少有一个參数;
  • 主构造函数的所有参数必须标注为 val 或者 var ;
  • 在 JVM 中如果构造函数是无参的则所有的属性必须有默认的值。
}

在 javakotlinn 中不需要自己动手去写一个 JavaBean,可以直接使用 DataClass使用 DataClass 编译器会默默地帮我们生成以下函数

  1. 编译器自动实现的函数举例

由于 data class 被编译器生成 JavaBean 时,是一个 final 类并且没有无参的構造函数,所以在使用过程非常不方便但是我们可以利用官方给出的插件来解决这些问题(noargallopen

  1. 经过上面5个步骤,编译器就会帮我去掉 final 關键字并且生成一个无参的构造方法,但是由于是在编译器做的操作所以在源代码中还是无法直接使用无参的构造函数,只能通过反射来使用
  1. 在项目目录中创建一个注解的目录 anno(我的完整包名是 mm.tm.jxcos.anno
  2. 在该目录下创建一个 NoArg 的注解类
<!-- 在合成的构造函数中调用实例初始化器 -->
}

我要回帖

更多关于 javakotlin 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信