本文为《Java Coding Problems》40-48题,问题涉及Objects, Immutability, and Switch Expressions (共18题)。
问题:null的判断。
思路:使用object != null
,或者Objects.isNull
、Objects.nonNull
。
代码如下:
// 判断列表中是否有null (过程式)
public boolean hasNull(List<Integer> integerList) {
if (integerList == null) {
return false;
}
for (Integer integer : integerList) {
if (integer == null) {
return true;
}
}
return false;
}
}
// 判断列表中是否有null (函数式)
public boolean hasNull(List<Integer> integerList) {
return Objects.nonNull(integerList) &&
integerList.stream()
.anyMatch(Objects::isNull);
}
NullPointerException
问题:检查null引用,并抛出自定义NullPointerException
。
思路:使用if
检查,使用throw new NullPointerException
抛出异常,或者使用Objects.requireNonNull
。
代码如下:
public void nullTest() {
String name = null;
if (name == null) {
throw new NullPointerException("Name cannot be null!");
}
// 等价于if (name == null) throw new ...
Objects.requireNonNull(name, "Name cannot be null!");
}
问题:检查null引用,并抛出特定异常。
思路:使用if
检查,然后抛出异常。
问题:检查null饮用,并在为null的时候设置默认值。
思路:使用if
检查,并设置默认值,或使用Objects.requireNonNullElseGet
。
代码如下:
public void nullTestSetDefaultValue() {
String name = null;
if (name == null) {
name = "default name";
}
// 等价于if (name == null) name = ...
name = Objects.requireNonNullElse(name, "default name");
}
问题:检查给定索引是否在[0, length)
范围内。
思路:使用Objects.checkIndex
检查(JDK9)。
问题:检查索引段是否在[0, length)范围内。
思路:使用Objects.checkFromToIndex
检查(JDK9)。
equals
和hashCode
如何工作问题:说明equals
和hashCode
在java中如何工作
思路:说明。
equals
和hashCode
是每个类都有的方法。Equals
用于比较对象,hashCode
用于生成类的hash值。
equals
默认实现是检查两个对象是否是同一个(内存地址相同),内部使用==
实现。hashCode
默认实现返回对象的内存地址。
equals
实现需要满足5个性质:
p1.equals(p1)
总是返回true
。p1.equals(p2)
和p2.equals(p1)
结果相同。p1.equals(p2)
,p2.equals(p3)
,那么p1.equals(p3)
。Null
: 所有对象与null
,不相等。
代码如下:@Override
public boolean equals(Object obj) {
if (this == obj) {
// 自反性
return true;
}
if (obj == null) {
// 不等于Null
return false;
}
if (getClass() != obj.getClass()) {
// 类型相同
return false;
}
// 其他属性比较
// ...
return true;
}
hashCode
实现需要满足:
equals
方法,必须重写hashCode
方法。问题:解释不可变对象。
思路:说明。
String
,Pattern
,LocalDate
是不可变的。问题:字符串是不可变的,这样设计有什么好处?
思路:说明。
在创建字符串常量时,所有的字符串常量会被保存在字符串常量池中,代码如下:
public static void internString() {
String t1 = "Hello";
String t2 = "Hello";
String t3 = "Hello";
if (t1 == t2 && t2 == t3) {
// t1, t2, t3指向常量池中的同一个对象
System.out.println("All String points to same memory address");
}
String t4 = new String("Hello");
if (t3 != t4) {
// 通过new String创建的对象在堆中
System.out.println("Not interned");
}
t4 = t4.intern();
if (t3 == t4) {
// 手动调用intern产生一个指向常量池对象的引用
System.out.println("Interned");
}
}
字符串不可变可以防止很多攻击。在使用Class.forName
时不会遭受String
改变的问题。
字符串可以在多个线程中共享,是线程安全的。
可以缓存hash code。
无法通过继承为String添加更多功能。
如果通过String
保存敏感数据,那这些数据可能长时间存在于字符串常量池中,存在安全隐患。
字符串常量池不大,可能导致内存溢出错误。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。