首页 >>  正文

java初始化方式

来源:baiyundou.net   日期:2024-09-23

【CSDN 编者按】Kotlin 和 Java 是如何解决 Null 问题?本文作者分享了解决思路。

原文链接:https://blog.frankel.ch/null-safety-java-vs-kotlin/

未经授权,禁止转载!

作者 | Nicolas Fränkel 责编 | 弯月出品 | CSDN(ID:CSDNnews)

在本文中,我想讨论一下 Kotlin 和 Java 是如何解决 Null 问题的。

可为 Null

相信每一位从事软件开发超过两年的人都听过下面这句话:

我把 Null 引用称为自己的十亿美元错误。它的发明是在 1965 年,那时我用一个面向对象语言(ALGOL W)设计了第一个全面的引用类型系统。我的目的是确保所有引用的使用都是绝对安全的,编译器会自动进行检查。但是我未能抵御住诱惑,加入了 Null 引用,仅仅是因为实现起来非常容易。结果导致了数不清的错误、漏洞和系统崩溃,可能在之后的 40 年中造成了十亿美元的损失。

—— 图灵奖得主 Tony Hoare

Null 背后的基本思想是能够定义一个未初始化的变量。当有人调用这类变量的某个成员时,运行时就会寻找变量的内存地址,结果就是引用失败,因为其后面没有任何东西。

许多编程语言都包含 Null 值,只不过名称不同罢了:

Python 有 None;

JavaScript 有 null;

Java、Scala 和 Kotlin 也有 null;

Ruby 有 nil;

以及其他等等。

有些不允许使用未初始化的值,比如 Rust。

Kotlin 中的 Null 安全性

如上所示,Kotlin 也有 null 值。只不过,null 融入到了类型系统中。在 Kotlin 中,每个类型 X 实际上都有两种类型:

X:不可为 null,类型 X 的任何变量都不可以为 null。编译器会确保这一点;

val str: String = null

上述代码无法通过编译。

X?:可以为 null。

val str: String? = null

上述代码可以编译。

既然 Kotlin 允许使用 null 值,为什么支持者们会鼓吹它具有 null 安全性呢?因为编译器会调用可能为 null 值(即可为空类型)的成员。

val str: String? = getNullableString()val int: Int? = str.toIntOrNull() #1

#1 无法通过编译。

修复上述代码的方式是,在调用成员之前,先检查变量是否为 null:

val str: String? = getNullableString()val int: Int? = if (str == null) null else str.toIntOrNull()

这种方法很模式化,Kotlin 提供了 null 安全的运算符:

val str: String? = getNullableString()val int: Int? = str?.toIntOrNull()

Java 中的 Null 安全性

如上,我们讨论了 Kotlin 管理 Null 值的方法,下面我们来看看 Java。

首先,Java 中既没有不可为 null 的类型,也没有 null 安全的运算符。因此,每个变量都有可能为 null,而且我们也的确应该如此思考。

MyString str = getMyString(); #1 Integer anInt = null; #2if (str != null) { anInt = str.toIntOrNull();}

#1 String 没有 toIntOrNull() 方法,所以我们假设 MyString 是一个包装类型,实际的操作交给 String。

#2 这里必须使用可变引用。

如果将多个调用放在一起,结果更糟,因为每个返回值都有可能为 null。为了安全着想,我们需要检查每个方法调用返回的值是否为 null。如下代码片段有可能抛出异常 NullPointerException:

var baz = getFoo().getBar().getBaz();

修复方法如下,但非常繁琐:

var foo = getFoo();var bar = null;var baz = null;if (foo != null) { bar = foo.getBar(); if (bar != null) { baz = bar.getBaz(); }}

出于这个原因,Java 8 引入了 Optional 类型。Optional 是一个包装,负责处理可能为 null 值的情况。在其他语言中,该类型被称为 Maybe、Option 等。

Java 语言的设计者建议,方法应返回:

如果 X 不可能为 null,则返回类型 X;

如果 X 可能为 null,则返回类型 Optional。

如果我们将上述方法的返回类型改为 Optional,就可以编写出 null 安全的代码,而且还可以获得不可变性:

final var baz = getFoo().flatMap(Foo::getBar) .flatMap(Bar::getBaz) .orElse(null);

对于这种方法,我认为核心问题在于,Optional 本身可以为 null。Java 语言本身无法确保 Optional 不为 null。此外,方法的输入参数不建议使用 Optional。

为了解决这个问题,网上涌现了很多基于注解的库:

然而,不同的库,处理方式也不同:

Spring 会在编译时生成警告消息;

FindBugs 需要专门执行;

Lombok 会生成一段检查 null 的代码,如果变量无论如何都会为 null,则抛出异常 NullPointerException。

总结当 Null 安全性不是一个大问题时,Java 可以被接受。因此,NullPointerException 异常会频繁发生。唯一安全的解决方案是将每个方法调用包装在 null 检查中。这种方式很有效,但同时也很模式化,代码也更加难以阅读。

开发人员称赞 Kotlin 带来了 Null 安全性,这是因为该语言的设计中融入了 Null 值处理机制。Java 这方面的处理远不如 Kotlin,因为 Java 语言架构师更加重视向后兼容性,而不是代码安全,这是设计上的决定。但是,作为一名开发人员,从 Null 安全性的角度出发,我认为 Kotlin 是比 Java 更有吸引力的选择。

","force_purephv":"0","gnid":"94cda4e64c9ace52c","img_data":[{"flag":2,"img":[{"desc":"","height":"80","s_url":"https://p0.ssl.img.360kuai.com/t013d73ffee4a20366b_1.gif","title":"","url":"https://p0.ssl.img.360kuai.com/t013d73ffee4a20366b.gif","width":"640"},{"desc":"","height":"532","title":"","url":"https://p0.ssl.img.360kuai.com/t01c1baa3d74504b07b.jpg","width":"1080"}]}],"original":0,"pat":"art_src_1,sexf,sex4,sexc,disu_label,fts0,sts0","powerby":"hbase","pub_time":1677030149000,"pure":"","rawurl":"http://zm.news.so.com/9903158623d4ebeb457e3e2d812c1005","redirect":0,"rptid":"a47df0a6e7d6f992","rss_ext":[],"s":"t","src":"CSDN","tag":[{"clk":"ktechnology_1:java","k":"java","u":""}],"title":"Kotlin 与 Java 如何解决 Null 问题?

古戚油1539Java对象初始化顺序是怎么样呢?
车保芬18213944533 ______ 当一个对象被创建时,初始化顺序: (1)设置成员的值为默认的初始值(0,false,null). (2)调用对象的构造方法(但是还没有执行构造方法体). (3)调用父类的构造方法. ...

古戚油1539Java提供了几种初始化对象中成员变量的方式?各自有什么特点? -
车保芬18213944533 ______ 1、构造器 创建对象时初始化成员变量,比较常见.2、初始化块 较少见,用于有特殊要求的类.3、方法 即Setter方法,虽然方便(不必在创建对象时一次性初始化),但是可能引发空指针异常.

古戚油1539java隐式的初始化是指什么? -
车保芬18213944533 ______ 1.Java对象何时被初始化 Java对象在其被创建时初始化,在Java代码中,有两种行为可以引起对象的创建.其中比较直观的一种,也就是通常所说的显式对象创建,就是通过new关键字来调用一个类的构造函数,通过构造函数来创建一个对象,...

古戚油1539在Java程序中可以通过哪几个途径对成员进行初始化? -
车保芬18213944533 ______ 要怎么理解初始化这个概念的.如果是new出一个对象时,就调用相应参数格式的构造函数,这个构造函数根据传递过来的参数在内存中分配一块区域,这是一个对象的初始化,主要指在内存中多了一块专门的区域.但是注意也有可能有些成员变量被赋予了相应的值,但是其他成员变量没有被赋予相应的值,则取默认值,比如int型变量默认为0,double型默认为0.0d.之后可以通过对象名.setX()方法对相应成员变量初始化.

古戚油1539Java程序的初始化过程 -
车保芬18213944533 ______ 当你实例化一个的时候,会先初始化该类的静态变量和其他变量,该类的变量放在栈中,对象放在堆中,方法放在方法区.

古戚油1539java中,什么初始化方法,初始化数组,初始化静态块,初始化是什么意思啊? -
车保芬18213944533 ______ 初始化就是赋值的意思,只不过这个赋值的时间是在对象创建时

古戚油1539请问java构造函数如何初始化成员变量的啊? -
车保芬18213944533 ______ java构造函数如何初始化成员变量的方式如下: 初始化顺序依据转换后对应的class类成员变量的初始化顺序依次执行,所以所有的静态成员变量都是先声明,后执行赋值的,而且赋值的顺序也是依照源代码对静态成员变量初始化的顺序进行的,注意:定义一个成员变量并直接初始化与在静态代码块中进行初始化是等价的,都是依据它们在源代码中定义的顺序进行的.

古戚油1539java中如何初始化输入流对象 -
车保芬18213944533 ______ 有很多输入流 举个例子 BufferedReader br = new BufferedReader(new FileReader(new File("E:/testE.txt"))); String str = ""; while ((str = br.readLine()) != null) { System.out.println(str); }

古戚油1539JAVA中怎么初始化对象数组? -
车保芬18213944533 ______ 定义并初始化方法一: String[] a = new String[3]; a[0] = "a"; a[1] = "b"; a[2] = "c"; 定义并初始化方法二: String[] b = new String[]{"a","b","c"};你可以看看北京尚学堂高琪300集讲解还是不错的,对你一定会有帮助

古戚油1539请问JAVA怎么实现初始化程序? -
车保芬18213944533 ______ 1:27class parent { int i = 9;//定义初始化 int j; parent() { System.out.println("i = " + i); j = 39; System.out.println("j = " + j); } static int x = prt("static parent.x initialized.");//静态定义初始化 static int prt(String s) { System.out.println(s); return 47; }...

(编辑:自媒体)
关于我们 | 客户服务 | 服务条款 | 联系我们 | 免责声明 | 网站地图 @ 白云都 2024