文档章节

抱歉!不要用Java的语法思维来写Kotlin

quanke_
 quanke_
发布于 03/09 09:09
字数 3570
阅读 5148
收藏 68
点赞 5
评论 44

写了多年的Java,直到看到Kotlin,原来代码可以如此优雅!

如果你是像我一样是一名优秀的Java开发者^_^,而且已经想用kotlin来实现你的程序,那么,抱歉!不要用Java的语法思维来写Kotlin,不要让kotlin的优雅埋没。如果你没有Java开发经验,下面的内容也对你会有帮助。。。

1.尽可能的少用 !!

个人感觉对于Null的检查是Koltin最语法糖的东西了,强制在编码过程中考虑空指针,因此《十亿美元的错误》,也许你不会再有这个机会犯错了(也许可以说成,你赚了十亿美金^_^)。

首先需要介绍是!!操作符。

!! 操作符:这是为空指针爱好者准备的,非空断言运算符(!!)将任何值转换为非空类型,若该值为空则抛出异常。我们可以写 a!! ,这会返回一个非空的 a 值 (例如:在我们例子中的 String)或者如果 a 为空,就会抛出一个 空指针 异常:

val b = a!!.length

所以,我们能不用!!操作符就不要用。。。

下面介绍几种方式避免使用!!操作符

1).多用 val 而不是 var

在 Kotlin 中 val代表只读,var代表可变。建议尽可能多的使用valval是线程安全的,并且必须在定义时初始化,所以不需要担心 null 的问题。只需要注意 val 在某些情况下也是可变的就行了。

val 和 var 是用于表示属性是否有 getter/setter:

  • var:同时有 getter 和 setter
  • val:只有 getter

所以,强烈推荐能用val的地方就用val

2).使用 lateinit

有些时候并不能用val,比如在spring boot接口测试中就不能使用val,对于这种情况,可以使用 lateinit 关键字。。

依赖倒转,对象的创建是通过spring完成的,而val要求定义的时候初始化

/**
 * Created by quanke on 2018/1/9.
 * Site:http://woquanke.com .
 */
@RunWith(SpringRunner::class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class ApplicationTests {

    val log = LogFactory.getLog(ApplicationTests::class.java)!!

    @Autowired
    lateinit var restTemplate: TestRestTemplate
    
    @Test
    fun `GET when given quanke then returns "Hello, quanke"`() {

        // Given
        val name = "quanke"

        // When
        val body = restTemplate.getForObject("/users/hello/{name}", String::class.java, name)

        // Then
        assertThat(body).isEqualTo("Hello, $name")
    }

}

注意:lateinit很好用,但也有坑

  • 访问未初始化的 lateinit 属性会导致 UninitializedPropertyAccessException。
  • lateinit 不支持基础数据类型,比如 Int。对于基础数据类型,我们可以这样:
private var mNumber: Int by Delegates.notNull<Int>()

3).Elvis 操作符

当b为可空引用时,我们可以使用if表达式处理

val l: Int = if (b != null) b.length else -1

但更加优雅的方式是使用Elvis 操作符?:

val l = b?.length ?: -1

如果 ?: 左侧表达式非空,elvis 操作符就返回其左侧表达式,否则返回右侧表达式。

注意:当且仅当左侧为空时,才会对右侧表达式求值。

4).也许可以尝试一下let函数

let函数一般与安全调用操作符一起使用,我们首先介绍安全调用操作?.

b?.length

如果 b 非空,就返回 b.length,否则返回 null,这个表达式的类型是 Int?。

安全调用在链式调用中很有用。例如,如果一个员工Quanke可能会(或者不会)分配给一个部门, 并且可能有另外一个员工是该部门的负责人,那么获取 Quanke 所在部门负责人(如果有的话)的名字,我们写作:

quanke?.department?.head?.name

如果任意一个属性(环节)为空,这个链式调用就会返回 null。

如果要只对非空值执行某个操作,安全调用操作符可以与 let 一起使用:

val listWithNulls: List<String?> = listOf("A", null)
for (item in listWithNulls) {
     item?.let { println(it) } // 输出 A 并忽略 null
}

还有一种常见的错误(放ide里面试试就知道什么错误了):

private var a: String? = null
fun aLetDemo() {
    if (a != null) {
        test(a)
    }
}

我们可以这样:

private var a: String? = null
fun aLetDemo() {
    if (a != null) {
        test(a!!)
    }
}

但是这样的后果就是你还是需要在test函数里处理空指针。

我们充分利用?.let的特点,更加优雅的解决这个编译错误,如下

private var a: String? = null
fun aLetDemo() {
    if (a != null) {
        a?.let {
            test(it)
        }
    }
}

2.少写点Util类和继承

很多时候框架提供给我的方法是比较原子,或者某些常用的方法框架并没有提供,Java一般是写一个工具类:

public final class StringUtil {

    /**
     * 删除所有的标点符号
     *
     * @param str 处理的字符串
     */
    public  static String trimPunct(String str) {
        if(isEmpty(str)){
            return "";
        }
        return str.replaceAll("[\\pP\\p{Punct}]", "");
    }
}

Kotlin可以通过扩展函数的形式实现:

/**
 * 删除所有的标点符号
 *
 * @param str 处理的字符串
 */
fun String.trimPunct(): String {
    return if (this.isEmpty()) {
        ""
    } else this.replace("[\\pP\\p{Punct}]".toRegex(), "")
}

调用:

fun main(args: Array<String>) {
    val a = "把我的标点符号去掉吧,全科。"
    print(a.trimPunct())
}

打印:

把我的标点符号去掉吧全科
Process finished with exit code 0

3.别再用+号拼接字符串

无论是Java还是Android开发,我们都会用到字符串拼接,比如进行日志输出等等。在Kotlin中,支持字符串模板,我们可以很轻松的完成一个字符串数的拼接,当然你可能会说使用StringBuilder性能更好,比如:

val site = "http://woquanke.com"
val sb: StringBuilder = StringBuilder()
sb.append("我的博客名字叫《我全科》,我的博客地址是:")
sb.append(site)
println(sb.toString())

但kotlin的字符串模版可以优雅的做这个事情:

val site = "http://woquanke.com"
println("我的博客名字叫《我全科》,我的博客地址是:$site")

4.也许可以忘记getters/setters了

我们经常创建一些只保存数据的类。在这些类中,一些标准函数往往是操作一下ide生成的。在 Kotlin 中,这叫做 数据类 并标记为 data:

data class User(val name: String, val age: Int)

data class 自动生成getter,setting,hashcode和equals等方法

5.请忘记三元运算符

在 Kotlin 中,if是一个表达式,即它会返回一个值。因此就不需要三元运算符(条件 ? 然后 : 否则),因为普通的 if 就能胜任这个角色。

// 作为表达式
val max = if (a > b) a else b

6.哪里还有switch

when 取代了类java 语言的 switch 操作符。其最简单的形式如下:

when (x) {
    1 -> print("x == 1")
    2 -> print("x == 2")
    else -> { // 注意这个块
        print("x is neither 1 nor 2")
    }
}

如果很多分支需要用相同的方式处理,则可以把多个分支条件放在一起,用逗号分隔:

when (x) {
    0, 1 -> print("x == 0 or x == 1")
    else -> print("otherwise")
}

可以用任意表达式(而不只是常量)作为分支条件

when (x) {
    parseInt(s) -> print("s encodes x")
    else -> print("s does not encode x")
}

也可以检测一个值在(in)或者不在(!in)一个区间或者集合中:

when (x) {
    in 1..10 -> print("x is in the range")
    in validNumbers -> print("x is valid")
    !in 10..20 -> print("x is outside the range")
    else -> print("none of the above")
}

另一种可能性是检测一个值是(is)或者不是(!is)一个特定类型的值。注意: 由于智能转换,你可以访问该类型的方法和属性而无需任何额外的检测。

fun hasPrefix(x: Any) = when(x) {
    is String -> x.startsWith("prefix")
    else -> false
}

when 也可以用来取代 if-else if链。 如果不提供参数,所有的分支条件都是简单的布尔表达式,而当一个分支的条件为真时则执行该分支:

when {
    x.isOdd() -> print("x is odd")
    x.isEven() -> print("x is even")
    else -> print("x is funny")
}

7.去你的ClassCastException

Kotlin智能转换(Smart Casts)

对于不可变的值,Kotlin一般不需要显式转换对象类型,编译器能跟踪is检查类型,在需要时会自动插入类型转换代码(安全):

fun classCast(a: Any) {
    if (a is String) {
        print(a.length) //编译器自动把a转换为String类型
    }
}

Kotlin编译器很聪明,能识别反向检查类型!is操作符,会自动插入类型转换代码:

if (a !is String) return
    print(a.length) //编译器自动把x转换为String类型:

    // ||右侧, a自动转换为String类型
    if (a !is String || a.length == 0) return

    // &&右侧, a自动转换为String类型
    if (a is String && a.length > 0) {
        print(a.length) // a 自动转换为字符串
    }

    //智能转换(smart casts)也用于when表达式和while循环
    when (a) {
        is Int -> print(a + 1)
        is String -> print(a.length + 1)
        is IntArray -> print(a.sum())
    }

如果不能保证变量在类型检查is/!is操作符和变量使用之间不可改变时,智能转换不能用。智能转换的适用条件或规则:

  • val局部变量-总是适用!
  • val属性-适用于private或internal,或者类型检查is/!is在声明属性的同一模块中执行;
  • 不适用于open的属性,或者具有自定义getter的属性!
  • var局部变量—适用于变量在类型检查和使用之间没有修改,且不在修改它的lambda中捕获!
  • var属性-不适用(因为该变量可随时被修改)

安全(可空)转换-操作符as?

为避免抛出异常,可用安全转换操作符as?,在失败时返回null

val a: String? = b as? String

尽管as?右边是一个非空类型String,但是as?转换失败时返回可空(null),换句话说就是,as?函数参数String不能为null,但是as?函数的返回值可以是null

8.真的要习惯Koltin的for循环,太强大了

Kotlin没有Java中的for(初始值;条件;增减步长)这个规则。但是Kotlin中对于for循环语句新增了其他的规则,来满足刚提到的规则。

  • for循环提供迭代器用来遍历任何东西
  • for循环数组被编译为一个基于索引的循环,它不会创建一个迭代器对象

新增的规则,去满足for(初始值;条件;增减步长)这个规则

递增

关键字:until 范围:until[n,m) => 即大于等于n,小于m

例:

  // 循环5次,且步长为1的递增
  for (i in 0 until 5){
    print("i => $i \t")
  }

输出结果为

i => 0  i => 1  i => 2  i => 3  i => 4

递减

关键字:downTo 范围:downTo[n,m] => 即小于等于n,大于等于m ,n > m 例:

// 循环5次,且步长为1的递减
for (i in 15 downTo 11){
    print("i => $i \t")
}

输出结果为:

i => 15     i => 14     i => 13     i => 12     i => 11 
符号(' .. ') 表示递增的循环的另外一种操作

使用符号( '..'). 范围:..[n,m]=> 即大于等于n,小于等于m 和until的区别,一是简便性。二是范围的不同。 例:

print("使用 符号`..`的打印结果\n")
for (i in 20 .. 25){
    print("i => $i \t")
}

println()

print("使用until的打印结果\n")
for (i in 20 until 25){
    print("i => $i \t")
}

输出结果为:

使用 符号..的打印结果

i => 20     i => 21     i => 22     i => 23     i => 24     i => 25  

使用until的打印结果

i => 20     i => 21     i => 22     i => 23     i => 24 
设置步长

关键字:step

例:

for (i in 10 until 16 step 2){
    print("i => $i \t")
}

输出结果为:

i => 10     i => 12     i => 14 

迭代

for循环提供一个迭代器用来遍历任何东西。 for循环数组被编译为一个基于索引的循环,它不会创建一个迭代器对象

遍历字符串

此用法在数据类型章节中的字符串类型中用到过。还不甚清楚的可以查看 Kotlin——最详细的数据类型介绍。

例:

for (i in "abcdefg"){
    print("i => $i \t")
}

输出结果为:

i => a  i => b  i => c  i => d  i => e  i => f  i => g  
遍历数组

此用法在数据类型章节中的数组类型中用到过。还不甚清楚的可以查看 Kotlin——最详细的数据类型介绍。

例:

var arrayListOne = arrayOf(10,20,30,40,50)
for (i in arrayListOne){
    print("i => $i \t")
}

输出结果为:

i => 10     i => 20     i => 30     i => 40     i => 50  
使用数组的indices属性遍历

例:

var arrayListTwo = arrayOf(1,3,5,7,9)
for (i in arrayListTwo.indices){
    println("arrayListTwo[$i] => " + arrayListTwo[i])
}

输出结果为:

arrayListTwo[0] => 1
arrayListTwo[1] => 3
arrayListTwo[2] => 5
arrayListTwo[3] => 7
arrayListTwo[4] => 9
使用数组的withIndex()方法遍历

例:

var arrayListTwo = arrayOf(1,3,5,7,9)
for ((index,value) in arrayListTwo.withIndex()){
    println("index => $index \t value => $value")
}

输出结果为:

index => 0   value => 1
index => 1   value => 3
index => 2   value => 5
index => 3   value => 7
index => 4   value => 9
使用列表或数组的扩展函数遍历

数组或列表有一个成员或扩展函数iterator()实现了Iterator<T>接口,且该接口提供了next()与hasNext()两个成员或扩展函数 其一般和while循环一起使用 可以查看Array.kt这个类。可以看见其中的iterator()函数,而这个函数实现了Iterator接口。

/**
  *   Creates an iterator for iterating over the elements of the array.
  */
public operator fun iterator(): Iterator<T>

查看Iterator.kt这个接口类,这个接口提供了hasNext()函数和next()函数。

public interface Iterator<out T> {

/**
  * Returns the next element in the iteration.
  */
public operator fun next(): T

/**
  * Returns `true` if the iteration has more elements.
  */
public operator fun hasNext(): Boolean
}

例:

var arrayListThree = arrayOf(2,'a',3,false,9)
var iterator: Iterator<Any> = arrayListThree.iterator()

while (iterator.hasNext()){
    println(iterator.next())
}

输出结果为:

2
a
3
false
9

关于for循环的内容来自《Kotlin——最详细的控制语句详解》

9.kotlin stream 真心可以

流式处理给我们的集合操作带来了很大的方便,其实Java 8 一样支持流式处理,我只是想在这里推广一下 stream。

下面举例:

val names = arrayOf("Amy", "Alex", "Bob", "Cindy", "Jeff", "Jack", "Sunny", "Sara", "Steven")  
  
//筛选S开头的人名  
val sName = names.filter { it.startsWith("S") }.toList()  
  
//按首字母分组并排序  
val nameGroup = names.groupBy { it[0] }  
        .toSortedMap( Comparator { key1, key2 -> key1.compareTo(key2) })  

关于更多流式处理,请自行搜索Java stream

10.少写点方法重载

因为kotlin支持默认参数,所以在封装方法时会少很多的方法重载的。

如果没有默认参数的需要实现下面的日志打印,需要写多个方法:

fun log(tag: String, content: String) {
    println("tag:$tag-->$content")
}

fun log( content: String) {
    log("quanke","")
}

使用默认参数只需要一个方法:

fun log(tag: String="quanke", content: String) {
    println("tag:$tag-->$content")
}

最后我还是想说:抱歉!不要用Java的语法思维来写Kotlin!

欢迎关注《Spring Boot 与 kotlin 实战》

欢迎关注公众号《全栈架构》

全栈架构

全栈有风险,菜鸟需谨慎

© 著作权归作者所有

共有 人打赏支持
quanke_

quanke_

粉丝 65
博文 52
码字总数 50680
作品 3
浦东
程序员
加载中

评论(44)

Raynor1
Raynor1

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

我觉得开源中国要好好把关下,这样的文章置顶不合适吧?@红薯
函数式的语言都是对象不可变(全部都是val修饰),所以就不用考虑到对应的线程是否安全的问题。不过它会带来对象复制的毛病哈。

Java和kotlin都不是纯粹的函数式,所以函数式的不可变在这里不起作用。函数式的不可变是原生的,kotlin不是原生的不可变。val只有final的效果,仅仅引用不可变,离线程安全差好几条街呢。引用不可变跟无状态和值不可变根本就不是一码事。
吓死我了。在你的眼里可能就只sync 等加锁。才是线程安全吧。。。。可能其他的安全操作。就不算线程安全了。。无知可能就是你的致命伤了。 若final 修饰final int a = 10; 这个int = 10的变量你多线程里面。怎么操作都是安全的啊。受不了了。我原本都不想回。实在没有办法。 。回一下。

真是逗,final用到基础变量上面的确有值不可变的特性,那用到对象变量上面呢?还有值不可变的特性?是线程安全的?别拿特例扯淡,还是你觉得kotlin中val只能用到基础变量上?kotlin中有基础变量么?kotlin中只有编译器优化时才有可能会优化成基础变量。纯函数式概念和kotlin都没了解清楚就把这两个混为一谈。所有基于jvm的语言基本上是不可能做到纯函数式的,因为他们要复用现有的生态库,你一句话就能让kotlin改变整个已有生态?真牛!
你也知道不知道 google的guava有个inmmutableMap啊。里面没有你想象的锁。但是就是不可变安全对象呢。。

你就继续打太极,继续东拉西扯。从kotlin的val扯到guava,你怎么不直接到lisp呢?

我哪句话跟你谈到锁了?你是太自以为是还是没长眼睛?
就你前面的那个谈的。在你的哪里 。可能除了sync字样的线程安全外。应该没有其他的实现办法了吧。。太恐怖了

我一直说的是"不可变","无状态"。在你这里成了只知道锁和sync?你家的锁跟“不可变”,"无状态"是一回事?
哎哟 不可变。我看看你前面留言的哦 。说final 修饰的。我觉得开源中国要好好把关下,这样的文章置顶不合适吧。你看看你之前的留言 。。还说final 修饰的和线程安全没有半毛钱关系 。和你写了代码final int i = 10;说这i是不是线程安全的么。又一句话都接不上了。老兄。你的逻辑和理论。根本找不到北。你的逻辑 。无法解释上面的代码 。你也不知道 。加上了final的int i 之后。set是编译器都不给过的。。你在装啥 。。
无著方知尘亦珍
无著方知尘亦珍

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

我觉得开源中国要好好把关下,这样的文章置顶不合适吧?@红薯
函数式的语言都是对象不可变(全部都是val修饰),所以就不用考虑到对应的线程是否安全的问题。不过它会带来对象复制的毛病哈。

Java和kotlin都不是纯粹的函数式,所以函数式的不可变在这里不起作用。函数式的不可变是原生的,kotlin不是原生的不可变。val只有final的效果,仅仅引用不可变,离线程安全差好几条街呢。引用不可变跟无状态和值不可变根本就不是一码事。
吓死我了。在你的眼里可能就只sync 等加锁。才是线程安全吧。。。。可能其他的安全操作。就不算线程安全了。。无知可能就是你的致命伤了。 若final 修饰final int a = 10; 这个int = 10的变量你多线程里面。怎么操作都是安全的啊。受不了了。我原本都不想回。实在没有办法。 。回一下。

真是逗,final用到基础变量上面的确有值不可变的特性,那用到对象变量上面呢?还有值不可变的特性?是线程安全的?别拿特例扯淡,还是你觉得kotlin中val只能用到基础变量上?kotlin中有基础变量么?kotlin中只有编译器优化时才有可能会优化成基础变量。纯函数式概念和kotlin都没了解清楚就把这两个混为一谈。所有基于jvm的语言基本上是不可能做到纯函数式的,因为他们要复用现有的生态库,你一句话就能让kotlin改变整个已有生态?真牛!
你也知道不知道 google的guava有个inmmutableMap啊。里面没有你想象的锁。但是就是不可变安全对象呢。。

你就继续打太极,继续东拉西扯。从kotlin的val扯到guava,你怎么不直接到lisp呢?

我哪句话跟你谈到锁了?你是太自以为是还是没长眼睛?
就你前面的那个谈的。在你的哪里 。可能除了sync字样的线程安全外。应该没有其他的实现办法了吧。。太恐怖了

我一直说的是"不可变","无状态"。在你这里成了只知道锁和sync?你家的锁跟“不可变”,"无状态"是一回事?
无著方知尘亦珍
无著方知尘亦珍

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

我觉得开源中国要好好把关下,这样的文章置顶不合适吧?@红薯
函数式的语言都是对象不可变(全部都是val修饰),所以就不用考虑到对应的线程是否安全的问题。不过它会带来对象复制的毛病哈。

Java和kotlin都不是纯粹的函数式,所以函数式的不可变在这里不起作用。函数式的不可变是原生的,kotlin不是原生的不可变。val只有final的效果,仅仅引用不可变,离线程安全差好几条街呢。引用不可变跟无状态和值不可变根本就不是一码事。
吓死我了。在你的眼里可能就只sync 等加锁。才是线程安全吧。。。。可能其他的安全操作。就不算线程安全了。。无知可能就是你的致命伤了。 若final 修饰final int a = 10; 这个int = 10的变量你多线程里面。怎么操作都是安全的啊。受不了了。我原本都不想回。实在没有办法。 。回一下。

真是逗,final用到基础变量上面的确有值不可变的特性,那用到对象变量上面呢?还有值不可变的特性?是线程安全的?别拿特例扯淡,还是你觉得kotlin中val只能用到基础变量上?kotlin中有基础变量么?kotlin中只有编译器优化时才有可能会优化成基础变量。纯函数式概念和kotlin都没了解清楚就把这两个混为一谈。所有基于jvm的语言基本上是不可能做到纯函数式的,因为他们要复用现有的生态库,你一句话就能让kotlin改变整个已有生态?真牛!
你也知道不知道 google的guava有个inmmutableMap啊。里面没有你想象的锁。但是就是不可变安全对象呢。。

你就继续打太极,继续东拉西扯。从kotlin的val扯到guava,你怎么不直接到lisp呢?
说你智障还不相信。guava的immutable对象就是使用final 的修饰。不可变思路做的线程安全的包呢。刚刚在说啥 呢?我就说你不懂还在这里装装装

给你科普下guava里有很多不可变的集合类型,不是线程安全的集合类型。董?不可变和线程安全在你眼里恐怕就是一个东西?官方都没说它是线程安全的,你比官方还厉害?谁不懂装懂?谁在乱用概念?
Raynor1
Raynor1

引用来自“无著方知尘亦珍”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

我觉得开源中国要好好把关下,这样的文章置顶不合适吧?@红薯
函数式的语言都是对象不可变(全部都是val修饰),所以就不用考虑到对应的线程是否安全的问题。不过它会带来对象复制的毛病哈。

Java和kotlin都不是纯粹的函数式,所以函数式的不可变在这里不起作用。函数式的不可变是原生的,kotlin不是原生的不可变。val只有final的效果,仅仅引用不可变,离线程安全差好几条街呢。引用不可变跟无状态和值不可变根本就不是一码事。
吓死我了。在你的眼里可能就只sync 等加锁。才是线程安全吧。。。。可能其他的安全操作。就不算线程安全了。。无知可能就是你的致命伤了。 若final 修饰final int a = 10; 这个int = 10的变量你多线程里面。怎么操作都是安全的啊。受不了了。我原本都不想回。实在没有办法。 。回一下。

真是逗,final用到基础变量上面的确有值不可变的特性,那用到对象变量上面呢?还有值不可变的特性?是线程安全的?别拿特例扯淡,还是你觉得kotlin中val只能用到基础变量上?kotlin中有基础变量么?kotlin中只有编译器优化时才有可能会优化成基础变量。纯函数式概念和kotlin都没了解清楚就把这两个混为一谈。所有基于jvm的语言基本上是不可能做到纯函数式的,因为他们要复用现有的生态库,你一句话就能让kotlin改变整个已有生态?真牛!
你也知道不知道 google的guava有个inmmutableMap啊。里面没有你想象的锁。但是就是不可变安全对象呢。。

你就继续打太极,继续东拉西扯。从kotlin的val扯到guava,你怎么不直接到lisp呢?

我哪句话跟你谈到锁了?你是太自以为是还是没长眼睛?
就你前面的那个谈的。在你的哪里 。可能除了sync字样的线程安全外。应该没有其他的实现办法了吧。。太恐怖了
无著方知尘亦珍
无著方知尘亦珍

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

我觉得开源中国要好好把关下,这样的文章置顶不合适吧?@红薯
函数式的语言都是对象不可变(全部都是val修饰),所以就不用考虑到对应的线程是否安全的问题。不过它会带来对象复制的毛病哈。

Java和kotlin都不是纯粹的函数式,所以函数式的不可变在这里不起作用。函数式的不可变是原生的,kotlin不是原生的不可变。val只有final的效果,仅仅引用不可变,离线程安全差好几条街呢。引用不可变跟无状态和值不可变根本就不是一码事。
吓死我了。在你的眼里可能就只sync 等加锁。才是线程安全吧。。。。可能其他的安全操作。就不算线程安全了。。无知可能就是你的致命伤了。 若final 修饰final int a = 10; 这个int = 10的变量你多线程里面。怎么操作都是安全的啊。受不了了。我原本都不想回。实在没有办法。 。回一下。

真是逗,final用到基础变量上面的确有值不可变的特性,那用到对象变量上面呢?还有值不可变的特性?是线程安全的?别拿特例扯淡,还是你觉得kotlin中val只能用到基础变量上?kotlin中有基础变量么?kotlin中只有编译器优化时才有可能会优化成基础变量。纯函数式概念和kotlin都没了解清楚就把这两个混为一谈。所有基于jvm的语言基本上是不可能做到纯函数式的,因为他们要复用现有的生态库,你一句话就能让kotlin改变整个已有生态?真牛!
你也知道不知道 google的guava有个inmmutableMap啊。里面没有你想象的锁。但是就是不可变安全对象呢。。

你就继续打太极,继续东拉西扯。从kotlin的val扯到guava,你怎么不直接到lisp呢?

我哪句话跟你谈到锁了?你是太自以为是还是没长眼睛?
无著方知尘亦珍
无著方知尘亦珍

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

我觉得开源中国要好好把关下,这样的文章置顶不合适吧?@红薯
函数式的语言都是对象不可变(全部都是val修饰),所以就不用考虑到对应的线程是否安全的问题。不过它会带来对象复制的毛病哈。

Java和kotlin都不是纯粹的函数式,所以函数式的不可变在这里不起作用。函数式的不可变是原生的,kotlin不是原生的不可变。val只有final的效果,仅仅引用不可变,离线程安全差好几条街呢。引用不可变跟无状态和值不可变根本就不是一码事。
吓死我了。在你的眼里可能就只sync 等加锁。才是线程安全吧。。。。可能其他的安全操作。就不算线程安全了。。无知可能就是你的致命伤了。 若final 修饰final int a = 10; 这个int = 10的变量你多线程里面。怎么操作都是安全的啊。受不了了。我原本都不想回。实在没有办法。 。回一下。

真是逗,final用到基础变量上面的确有值不可变的特性,那用到对象变量上面呢?还有值不可变的特性?是线程安全的?别拿特例扯淡,还是你觉得kotlin中val只能用到基础变量上?kotlin中有基础变量么?kotlin中只有编译器优化时才有可能会优化成基础变量。纯函数式概念和kotlin都没了解清楚就把这两个混为一谈。所有基于jvm的语言基本上是不可能做到纯函数式的,因为他们要复用现有的生态库,你一句话就能让kotlin改变整个已有生态?真牛!
你也知道不知道 google的guava有个inmmutableMap啊。里面没有你想象的锁。但是就是不可变安全对象呢。。

你就继续打太极,继续东拉西扯。从kotlin的val扯到guava,你怎么不直接到lisp呢?
无著方知尘亦珍
无著方知尘亦珍

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

我觉得开源中国要好好把关下,这样的文章置顶不合适吧?@红薯
函数式的语言都是对象不可变(全部都是val修饰),所以就不用考虑到对应的线程是否安全的问题。不过它会带来对象复制的毛病哈。

Java和kotlin都不是纯粹的函数式,所以函数式的不可变在这里不起作用。函数式的不可变是原生的,kotlin不是原生的不可变。val只有final的效果,仅仅引用不可变,离线程安全差好几条街呢。引用不可变跟无状态和值不可变根本就不是一码事。
吓死我了。在你的眼里可能就只sync 等加锁。才是线程安全吧。。。。可能其他的安全操作。就不算线程安全了。。无知可能就是你的致命伤了。 若final 修饰final int a = 10; 这个int = 10的变量你多线程里面。怎么操作都是安全的啊。受不了了。我原本都不想回。实在没有办法。 。回一下。

真是逗,final用到基础变量上面的确有值不可变的特性,那用到对象变量上面呢?还有值不可变的特性?是线程安全的?别拿特例扯淡,还是你觉得kotlin中val只能用到基础变量上?kotlin中有基础变量么?kotlin中只有编译器优化时才有可能会优化成基础变量。纯函数式概念和kotlin都没了解清楚就把这两个混为一谈。所有基于jvm的语言基本上是不可能做到纯函数式的,因为他们要复用现有的生态库,你一句话就能让kotlin改变整个已有生态?真牛!
哎哟 。看看你说得话。。。就知道你的智商有多少的无知final int a = 10 ,你这个变量还能上Set方法?真是吓死了。java没有学好。还在这里吹吹吹。。你要不要脸。。

你就闭着眼睛继续扯,你看我回答的了么?那么大的基础变量和对象变量几个字看不见么?眼睛都没长的就别跟我谈智商。
Raynor1
Raynor1

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

我觉得开源中国要好好把关下,这样的文章置顶不合适吧?@红薯
函数式的语言都是对象不可变(全部都是val修饰),所以就不用考虑到对应的线程是否安全的问题。不过它会带来对象复制的毛病哈。

Java和kotlin都不是纯粹的函数式,所以函数式的不可变在这里不起作用。函数式的不可变是原生的,kotlin不是原生的不可变。val只有final的效果,仅仅引用不可变,离线程安全差好几条街呢。引用不可变跟无状态和值不可变根本就不是一码事。
吓死我了。在你的眼里可能就只sync 等加锁。才是线程安全吧。。。。可能其他的安全操作。就不算线程安全了。。无知可能就是你的致命伤了。 若final 修饰final int a = 10; 这个int = 10的变量你多线程里面。怎么操作都是安全的啊。受不了了。我原本都不想回。实在没有办法。 。回一下。

真是逗,final用到基础变量上面的确有值不可变的特性,那用到对象变量上面呢?还有值不可变的特性?是线程安全的?别拿特例扯淡,还是你觉得kotlin中val只能用到基础变量上?kotlin中有基础变量么?kotlin中只有编译器优化时才有可能会优化成基础变量。纯函数式概念和kotlin都没了解清楚就把这两个混为一谈。所有基于jvm的语言基本上是不可能做到纯函数式的,因为他们要复用现有的生态库,你一句话就能让kotlin改变整个已有生态?真牛!
你也知道不知道 google的guava有个inmmutableMap啊。里面没有你想象的锁。但是就是不可变安全对象呢。。
Raynor1
Raynor1

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

我觉得开源中国要好好把关下,这样的文章置顶不合适吧?@红薯
函数式的语言都是对象不可变(全部都是val修饰),所以就不用考虑到对应的线程是否安全的问题。不过它会带来对象复制的毛病哈。

Java和kotlin都不是纯粹的函数式,所以函数式的不可变在这里不起作用。函数式的不可变是原生的,kotlin不是原生的不可变。val只有final的效果,仅仅引用不可变,离线程安全差好几条街呢。引用不可变跟无状态和值不可变根本就不是一码事。
吓死我了。在你的眼里可能就只sync 等加锁。才是线程安全吧。。。。可能其他的安全操作。就不算线程安全了。。无知可能就是你的致命伤了。 若final 修饰final int a = 10; 这个int = 10的变量你多线程里面。怎么操作都是安全的啊。受不了了。我原本都不想回。实在没有办法。 。回一下。

真是逗,final用到基础变量上面的确有值不可变的特性,那用到对象变量上面呢?还有值不可变的特性?是线程安全的?别拿特例扯淡,还是你觉得kotlin中val只能用到基础变量上?kotlin中有基础变量么?kotlin中只有编译器优化时才有可能会优化成基础变量。纯函数式概念和kotlin都没了解清楚就把这两个混为一谈。所有基于jvm的语言基本上是不可能做到纯函数式的,因为他们要复用现有的生态库,你一句话就能让kotlin改变整个已有生态?真牛!
哎哟 。看看你说得话。。。就知道你的智商有多少的无知final int a = 10 ,你这个变量还能上Set方法?真是吓死了。java没有学好。还在这里吹吹吹。。你要不要脸。。
无著方知尘亦珍
无著方知尘亦珍

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

引用来自“Raynor1”的评论

引用来自“无著方知尘亦珍”的评论

我觉得开源中国要好好把关下,这样的文章置顶不合适吧?@红薯
函数式的语言都是对象不可变(全部都是val修饰),所以就不用考虑到对应的线程是否安全的问题。不过它会带来对象复制的毛病哈。

Java和kotlin都不是纯粹的函数式,所以函数式的不可变在这里不起作用。函数式的不可变是原生的,kotlin不是原生的不可变。val只有final的效果,仅仅引用不可变,离线程安全差好几条街呢。引用不可变跟无状态和值不可变根本就不是一码事。
吓死我了。在你的眼里可能就只sync 等加锁。才是线程安全吧。。。。可能其他的安全操作。就不算线程安全了。。无知可能就是你的致命伤了。 若final 修饰final int a = 10; 这个int = 10的变量你多线程里面。怎么操作都是安全的啊。受不了了。我原本都不想回。实在没有办法。 。回一下。

真是逗,final用到基础变量上面的确有值不可变的特性,那用到对象变量上面呢?还有值不可变的特性?是线程安全的?别拿特例扯淡,还是你觉得kotlin中val只能用到基础变量上?kotlin中有基础变量么?kotlin中只有编译器优化时才有可能会优化成基础变量。纯函数式概念和kotlin都没了解清楚就把这两个混为一谈。所有基于jvm的语言基本上是不可能做到纯函数式的,因为他们要复用现有的生态库,你一句话就能让kotlin改变整个已有生态?真牛!
Xtend语言(1):独辟蹊径的JVM语言

我是2004年开始学习Java语言的,那时候的Java是1.4版本,说实在的,最新的Java10跟我一开始学习Java时候的语法变化并不大。我相信很多人都会跟我有相同的感受:Java写的越多就越觉得语法十分...

神思者l ⋅ 06/05 ⋅ 0

从 Java 到 Kotlin,再从 Kotlin 回归 Java

由于此博客文章引起高度关注和争议,我们认为值得在Allegro上增加一些关于我们如何工作和做出决策的背景。Allegro拥有超过50个开发团队可以自由选择被我们PaaS所支持的技术。我们主要使用Jav...

oschina ⋅ 05/31 ⋅ 0

从Java到Kotlin,然后又回到Java!

最近Java与kotlin语言之争又有点小热,大概是因为某位当初吹捧Java的大神来华兜售其kotlin新书有关,但是与此同时相反观点也是不断涌现,Allegro团队就在他们的博客发表这篇文章,从Java到K...

欧阳海阳 ⋅ 05/28 ⋅ 0

Kotlin2.4while和for循环

Kotlin的迭代应该是和Java最接近的。while循环和Java完全一样。for循环仅以唯一一种形式存在,和Java的for-each循环一直。 2.4.1while循环 Kotlin中有while循环和do-while循环,它们的语法和...

无心下棋 ⋅ 05/13 ⋅ 0

为什么我会弃Java,选择了Kotlin——专访《Java编程思想》作者 Bruce Eckel

点击上方“CSDN”,选择“置顶公众号” 关键时刻,第一时间送达! 这是前不久我们发布《Kotlin或将取代Java》一文之后,来自网友们的部分声音。 可以看到:作为编程语言界的老大——Java仍然...

csdnnews ⋅ 05/30 ⋅ 0

浅谈Kotlin(一):简介及Android Studio中配置

浅谈Kotlin(一):简介及Android Studio中配置 浅谈Kotlin(二):基本类型、基本语法、代码风格 浅谈Kotlin(三):类 浅谈Kotlin(四):控制流 前言:   今日新闻:谷歌宣布,将Kotli...

听着music睡 ⋅ 2017/05/18 ⋅ 0

Kotlin 泛型 VS Java 泛型

建议先阅读我的上一篇文章 -- Java 泛型 和 Java 泛型一样,Kotlin 泛型也是 Kotlin 语言中较难理解的一个部分。Kotlin 泛型的本质也是参数化类型,并且提供了编译时强类型检查,实际上也是伪...

JohnnyShieh ⋅ 06/11 ⋅ 0

Java 已老,Kotlin 或将取而代之!

点击上方“CSDN”,选择“置顶公众号” 关键时刻,第一时间送达! Java已经成为历史。它无法发展成现代语言,同时保证向后兼容性。但它为我们带来了最好的JVM生态系统,并引导了许多优秀语言...

CSDN ⋅ 05/12 ⋅ 0

搞定Kotlin Receiver

Kotlin官方文档中没有针对Receiver的专题讲解,但这个知识点却贯穿在了整个基础体系中。这节课我们将彻底揭开Receiver的神秘面纱,带你一探究竟。 什么是Receiver 解释这个概念之前,先想一想...

欧阳锋 ⋅ 04/26 ⋅ 0

兄弟来开车 我们一起学Kotlin

为啥子要学kotlin 没有为啥,语法简介,大佬都在玩,跟风 先看看跟java的差异哈 貌似没啥子差别我们继续往下走 下面是个普通java model 类 来看一下怎么调用 在java中调用 在kotlin中调用 是...

no白菜 ⋅ 06/09 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

vim基础-编辑模式-命令模式

编辑模式:可以编辑修改文件。编辑模式下 按“esc”键返回一般模式。 按一次“Insert”键 (一般在键盘回格键右边)作用和“i”一样表示“插入”。按两次“Insert”键表示“替换”,作用为:...

ZHENG-JY ⋅ 17分钟前 ⋅ 0

MaxCompute读取分析OSS非结构化数据的实践经验总结

摘要: 本文背景 很多行业的信息系统中,例如金融行业的信息系统,相当多的数据交互工作是通过传统的文本文件进行交互的。此外,很多系统的业务日志和系统日志由于各种原因并没有进入ELK之类...

阿里云云栖社区 ⋅ 22分钟前 ⋅ 0

Linux操作系统有何优势?Linux学习

  当今世界流行的操作系统有3大类,Linux、Mac OS和Windows操作系统,Linux操作系统因其开源、免费、跨平台、良好的界面等特性,深受广大程序员们的青睐!   Linux操作系统被广泛的应用于...

老男孩Linux培训 ⋅ 24分钟前 ⋅ 0

Spring Cloud Spring Boot mybatis分布式微服务云架构 开发Web应用

静态资源访问 在我们开发Web应用的时候,需要引用大量的js、css、图片等静态资源。 默认配置 Spring Boot默认提供静态资源目录位置需置于classpath下,目录名需符合如下规则: /static /pub...

itcloud ⋅ 28分钟前 ⋅ 0

6月19日任务 设置更改root密码、连接mysql、mysql常用命令

13.1 设置更改root密码 1. /usr/local/mysql/bin/mysql -uroot 设置环境变量 : export PATH=$PATH:/usr/local/mysql/bin/ 永久生效: vim /etc/profile 加入 export PATH=$PATH:/usr/local/m......

吕湘颖 ⋅ 29分钟前 ⋅ 0

MaxCompute读取分析OSS非结构化数据的实践经验总结

摘要: 本文背景 很多行业的信息系统中,例如金融行业的信息系统,相当多的数据交互工作是通过传统的文本文件进行交互的。此外,很多系统的业务日志和系统日志由于各种原因并没有进入ELK之类...

猫耳m ⋅ 31分钟前 ⋅ 0

Spring MVC controller,return重定向redirect:

@RequestMapping(value="/save",method=RequestMethod.POST)public String doSave(Course course) {log.debug("Info of Course");log.debug(ReflectionToStringBuilder.toStr......

颖伙虫 ⋅ 38分钟前 ⋅ 0

JavaSE——线程介绍

声明:本栏目所使用的素材都是凯哥学堂VIP学员所写,学员有权匿名,对文章有最终解释权;凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记。 线程: 介绍:管线程叫多任务处理,首先你得知道...

凯哥学堂 ⋅ 42分钟前 ⋅ 0

ORM——使用spring jpa data实现逻辑删除

前言 在业务中是忌讳物理删除数据的,数据的这个对于一个IT公司可以说是最核心的资产,如果删除直接就物理删除,无疑是对核心资产的不重视,可能扯的比较远,本文最主要是想通过spring jpa ...

alexzhu592 ⋅ 48分钟前 ⋅ 0

CDN caching

Incapsula应用感知CDN使用智能分析和频率分析来动态缓存内容,并最大限度地提高效率。确保可直接从RAM获取最常访问的资源,而不依赖于较慢的访问机制。 1、 静态内容缓存 Incapsula缓存静态内...

上树的熊 ⋅ 51分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部