当前位置: 首页 > 科技观察

与Java编程语言相比,Kotlin有哪些优势?

时间:2023-03-13 19:07:49 科技观察

随着计算机语言的发展,以成本为核心的驱动力推动了汇编、C、C++、Java、Kotlin的发展。目的是让开发者更好的专注于业务,而不用过多关注语言本身的处理。近年来,更高级的语言又开始流行起来,被称为现代编程语言,比如Rust、Go、Kotlin和TypeScript。现代核心的原因,我认为可以归纳为以下几点:更容易上手类型推断空指针安全内置并发支持减少模板代码(简洁)更容易操作集合更智能的垃圾收集以上不一定完整,但在一定程度上概括了现代语言的特点。接下来,我们就通过Kotlin和Java的对比来看一下Kotlin的优势。newobjectnewanobject是编程中最常用的操作之一,让我们先来看看Java中如何newanobject。Listlist=newArrayList();list.add("helloworld");在Java中,我们需要定义一个变量,然后通过new关键字声明一个ArrayList的实例,这样我们就可以使用了。但在Kotlin中,newanobject更简洁。varlist:ArrayList=ArrayList()直接省略了new关键字。类型推断对于上面的Kotlin代码,我们可以完全省略variable:后面的类型声明,因为kotlin可以自己推断。你认为vallist=ArrayList()更简洁吗?我们的开发效率也更高。空指针安全在Java中,变量、方法参数等可以为null,但在Kotlin中,默认是不允许的。通过这种强制性的限制,可以更好的避免空指针异常。varlist=ArrayList()list=null对于上面的代码,你在编译时会得到一个错误信息:Nullcannotbeavalueofanon-nulltypeArrayList如果我们真的需要空赋值怎么办?在Kotlin中,开发人员需要自己显示语句。能。varlist:Array?=null如上所示,只需添加?在类型之后。但请注意,我们不提倡这种做法。在实际开发中,你会发现大部分都是为了兼容Java代码而使用的。属性我们通常将数据和数据处理封装到一个类中。如果类中有私有字段,我们还需要提供getter和setter方法来提供访问和修改字段的方法。//Person.javapublicclassPerson{privateStringname;publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}}//Main.javapublicstaticvoidmain(String[]args){Personp=newPerson();p.setName("张三");System.out.println(p.getName());}上面是我们用Java实现的一个Person类,定义了name私有字段,并提供了getter和setter方法,方便我们使用。通过上面的代码可以看出,为了实现一个名字的存储,我们写了很多代码。如果一个类中有很多字段,我们会写更多不必要的getter和setter方法。现在让我们看看如何在Kotlin中实现上述功能。//Person.ktclassPerson{varname:String=""}//main.ktfunmain(){valp=Person()p.name="张三"println(p.name)}没错,就这么简单,只需要只需几行代码,就可以实现和Java一样的功能,因为Kotlin可以帮我们自动生成getters、setters等模板代码,为我们省去了很多工作,大大提高了我们的开发效率,而且整个代码也更有效率。简洁的。这里需要注意的是,如果字段声明为val,则只会生成getter方法,因为val是不可修改的,相当于Java中的final修饰符;如果字段是var,getter和setter方法都可以生成,那么就可以给字段赋值了。数据类的简单Kotlin不仅体现在getter和setter方法上,也体现在数据类上。数据类是数据容器,用于存储数据。一个好的数据类声明,不仅要有私有字段、getter、setter方法,还要实现toString、equals、hashCode方法,这样才能打印、比较,更好地存储在map中。仍然以Person类为例,一个合格的数据类代码如下:名称;}@Overridepublicbooleanequals(Objecto){if(this==o)returntrue;if(o==null||getClass()!=o.getClass())returnfalse;Personperson=(Person)o;returnObjects.equals(名字,人.名字);}@OverridepublicinthashCode(){returnname!=null?name.hashCode():0;}@OverridepublicStringtoString(){return"Person{"+"name='"+name+'\''+'}';}}看我们的Java实现,需要30多行代码才能实现。如果我们使用Kotlin会发生什么?dataclassPerson(valname:String){}只需要这么一行代码,上面的Java功能就实现了。这里的关键是一个数据修饰符,是不是很酷?并发性Kotlin提供协程来实现并发性,比Java的Thread和Executor更轻量、更简洁。我们来比较一下并发的基本实现。publicstaticvoidmain(String[]args)throwsInterruptedException{newMyThread().start();System.out.println(Thread.currentThread().getName()+":main");//保证JVM存活Thread.sleep(1000);}privatestaticclassMyThreadextendsThread{@Overridepublicvoidrun(){try{Thread.sleep(500);System.out.println(Thread.currentThread().getName()+":Thread");}catch(InterruptedExceptione){e.printStackTrace();}}}运行查看输出结果,发现MyThread并没有阻塞main的执行,也就是说是并发的。main:mainThread-0:Thread但注意Java使用了两个线程,一个是main,另一个是Thread-0。同样的功能,我们现在用kotlin来实现:funmain(){runBlocking{launch{delay(500)println("${Thread.currentThread().name}:Thread")}println("${Thread.currentThread().name}:main")}}比Java更简洁,再看打印输出:main:mainmain:Thread其实是在同一个线程上并发实现的,减少了一个线程的应用开销。更高效,这也是kotlin提出的coroutine的概念。如果我们不希望它在主线程上执行,我们可以通过切换调度器来实现。launch(Dispatchers.IO)只需要将上面代码的launch替换成launch(Dispatchers.IO),这样调度器就会给我们分配一个IO线程池来执行我们的代码。如果我们用Java来实现,需要自己定义线程池,提交Runnable,整个代码非常多。main:mainDefaultDispatcher-worker-1:Threadkotlin的协程非常强大简洁。通过上面的例子,还不能完全展示它的特点。协程上下文、调度器、Flow、Channel等剩余能力大家可以自行探索。总结通过上面的比较,我们应该可以看出一门现代编程语言的特点和优势,而我们并没有完全列出Kotlin有用的特性,比如方便的集合操作、属性委托、扩展函数等等。