我正试图了解为什么需要让。在下面的示例中,我有一个带有功能GiveMeFive的Test类:
public class Test() {
fun giveMeFive(): Int {
return 5
}
}
给出以下代码:
var test: Test? = Test()
var x: Int? = test?.giveMeFive()
test = null
x = test?.giveMeFive()
x = test?.let {it.giveMeFive()}
x设置为5,然后将test设置为null后,调用以下任一语句返回x的null。鉴于在null引用上调用方法会跳过该调用并将x设置为null,为什么我需要使用let?在某些情况下只是?不能正常工作,需要租借吗?
此外,如果被调用的函数未返回任何内容,则为?。会跳过该呼叫,并且我也不需要?.let。
答案 0 :(得分:4)
let()
fun <T, R> T.let(f: (T) -> R): R = f(this)
let()是作用域函数:每当您要为代码的特定范围定义变量时都可以使用它,但不能超出范围。使您的代码保持良好的独立性非常有用,这样您就不会有变量“泄漏出去”:可以通过它们应有的位置进行访问。
DbConnection.getConnection().let { connection ->
}
//连接在这里不再可见
let()也可以用作测试null的替代方法:
val map : Map<String, Config> = ...
val config = map[key]
// config is a "Config?"
config?.let {
// This whole block will not be executed if "config" is null.
// Additionally, "it" has now been cast to a "Config" (no
question mark)
}
答案 1 :(得分:2)
如果要链接未在链接类型上定义的函数调用,则需要使用// Not defined inside the Test class
fun giveMeFive(t: Test) {
return 5
}
。
比方说,您的函数的定义是这样的:
Test
现在,如果您有一个可为空的let
,并且想在链中调用此函数,则必须使用val x = test?.let { giveMeFive(it) }
:
// Herokuapp.com has a root cert that won't parse:
// DigiCert SHA2 High Assurance Server CA.pem
// E (48067) esp-tls: mbedtls_x509_crt_parse returned -0x112c
static const char *heroku_server_root_cert_pem = "-----BEGIN CERTIFICATE-----\r\n\
MIIEsTCCA5mgAwIBAgIQBOHnpNxc8vNtwCtCuF0VnzANBgkqhkiG9w0BAQsFADBs\r\n\
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\r\n\
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j\r\n\
ZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowcDEL\r\n\
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3\r\n\
LmRpZ2ljZXJ0LmNvbTEvMC0GA1UEAxMmRGlnaUNlcnQgU0hBMiBIaWdoIEFzc3Vy\r\n\
YW5jZSBTZXJ2ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2\r\n\
4C/CJAbIbQRf1+8KZAayfSImZRauQkCbztyfn3YHPsMwVYcZuU+UDlqUH1VWtMIC\r\n\
Kq/QmO4LQNfE0DtyyBSe75CxEamu0si4QzrZCwvV1ZX1QK/IHe1NnF9Xt4ZQaJn1\r\n\
itrSxwUfqJfJ3KSxgoQtxq2lnMcZgqaFD15EWCo3j/018QsIJzJa9buLnqS9UdAn\r\n\
4t07QjOjBSjEuyjMmqwrIw14xnvmXnG3Sj4I+4G3FhahnSMSTeXXkgisdaScus0X\r\n\
sh5ENWV/UyU50RwKmmMbGZJ0aAo3wsJSSMs5WqK24V3B3aAguCGikyZvFEohQcft\r\n\
bZvySC/zA/WiaJJTL17jAgMBAAGjggFJMIIBRTASBgNVHRMBAf8ECDAGAQH/AgEA\r\n\
MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw\r\n\
NAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy\r\n\
dC5jb20wSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQuY29t\r\n\
L0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDA9BgNVHSAENjA0MDIG\r\n\
BFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQ\r\n\
UzAdBgNVHQ4EFgQUUWj/kK8CB3U8zNllZGKiErhZcjswHwYDVR0jBBgwFoAUsT7D\r\n\
aQP4v0cB1JgmGggC72NkK8MwDQYJKoZIhvcNAQELBQADggEBABiKlYkD5m3fXPwd\r\n\
aOpKj4PWUS+Na0QWnqxj9dJubISZi6qBcYRb7TROsLd5kinMLYBq8I4g4Xmk/gNH\r\n\
E+r1hspZcX30BJZr01lYPf7TMSVcGDiEo+afgv2MW5gxTs14nhr9hctJqvIni5ly\r\n\
/D6q1UEL2tU2ob8cbkdJf17ZSHwD2f2LSaCYJkJA69aSEaRkCldUxPUd1gJea6zu\r\n\
xICaEnL6VpPX/78whQYwvwt/Tv9XBZ0k7YXDK/umdaisLRbvfXknsuvCnQsH6qqF\r\n\
0wGjIChBWUMo0oHjqvbsezt3tkBigAVBRQHvFwY+3sAzm2fTYS5yh+Rp/BIAV0Ae\r\n\
cPUeybQ=\r\n\
-----END CERTIFICATE----";
//Let's Encrypt Authority X3.pem
static const char *webhook_server_root_cert_pem = "-----BEGIN CERTIFICATE-----\r\n\
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\r\n\
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\r\n\
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\r\n\
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\r\n\
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\r\n\
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\r\n\
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\r\n\
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\r\n\
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\r\n\
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\r\n\
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\r\n\
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\r\n\
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\r\n\
bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\r\n\
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\r\n\
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\r\n\
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\r\n\
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\r\n\
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\r\n\
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\r\n\
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\r\n\
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\r\n\
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\r\n\
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\r\n\
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\r\n\
-----END CERTIFICATE-----";
static void parse_certs() {
mbedtls_x509_crt *global_cacert = (mbedtls_x509_crt *)calloc(1, sizeof(mbedtls_x509_crt));
if (global_cacert == NULL) {
printf("global_cacert not allocated");
return;
}
mbedtls_x509_crt_init(global_cacert);
int ret;
ret = mbedtls_x509_crt_parse(global_cacert,
(const unsigned char *) heroku_server_root_cert_pem,
strlen(heroku_server_root_cert_pem) + 1);
printf("Parse of herokuapp.com root cert is %d\n", ret);
ret = mbedtls_x509_crt_parse(global_cacert,
(const unsigned char *) webhook_server_root_cert_pem,
strlen(webhook_server_root_cert_pem) + 1);
printf("Parse of webhook.site root cert is %d\n", ret);
free(global_cacert);
}
答案 2 :(得分:1)
Kotlin中的.let {}扩展功能:
将作为对象引用,作为调用.let{}
的参数。
返回使用let{}
函数返回的任何非原始数据类型的值。默认情况下,它返回undefined
类的kotlin.Any
值。
软件包kotlin中的声明:
public inline fun <T, R> T.let(block: (T) -> R): R {
return block(this)
}
简单的实际演示,以了解.let{}
扩展功能在Kotlin中的工作方式。
示例代码1:-
val builder = StringBuilder("Hello ")
println("Print 0: $builder")
val returnVal = builder.let { arg ->
arg.append("World")
println("Print 1: $arg")
"Done" // Returnning some string
}
println("Print 2: $builder")
println("Print 3: $returnVal")
示例代码1输出:-
Print 0: Hello
Print 1: Hello World
Print 2: Hello World
Print 3: Done
在示例代码1中:
我们用初始化值“ Hello”创建了StringBuilder类型的最终对象。
在
builder.let{}
中,构建器对象引用将传递到arg
。在这里,输出
Print 2: Hello World
和Print 3: Hello World
表示builder
和arg
都指向相同的StringBuilder
{{1 }}。这就是为什么它们都打印相同的object-reference
值的原因。在
String
功能块的最后一行中,我们返回.let{}
"Done"
的值,该值将分配给String
。*因此,我们从
returnVal
获得了Print 3: Done
的输出。
示例代码2:-
returnVal
示例代码2输出:-
val builder = StringBuilder("Hello ")
println("Print 0: $builder")
val returnVal = builder.let { arg ->
arg.append("World")
println("Print 1: $arg")
arg.length
}
println("Print 2: $builder")
println("Print 3: $returnVal") // Now return val is int = length of string.
在示例代码2中:
有什么区别:
在
Print 0: Hello Print 1: Hello World Print 2: Hello World Print 3: 11
功能块的最后一行中,我们返回的.let{}
值等于StringBuilder对象Int
的长度,该对象在此代码行的值为{{1} }。因此,将arg
类型的 length ="Hello World"
分配给11
。*因此,我们从
Int
得到returnVal
。
也可以尝试以下操作:-
快乐编码...
答案 3 :(得分:0)
有趣
.let 块不等于多线程
val x? = 空
if(x == null) {
}
和
x?.let{
}
.let 块是线程安全的