前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Objects, Immutability, and Switch Expressions 40-48

Objects, Immutability, and Switch Expressions 40-48

原创
作者头像
luoheng
发布2022-10-23 14:04:03
4670
发布2022-10-23 14:04:03
举报
文章被收录于专栏:luoheng

本文为《Java Coding Problems》40-48题,问题涉及Objects, Immutability, and Switch Expressions (共18题)。

40. 函数式和过程式的判空

问题:null的判断。

思路:使用object != null,或者Objects.isNullObjects.nonNull

代码如下:

代码语言:java
复制
// 判断列表中是否有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);
}

41. 检查null引用,并抛出自定义NullPointerException

问题:检查null引用,并抛出自定义NullPointerException

思路:使用if检查,使用throw new NullPointerException抛出异常,或者使用Objects.requireNonNull

代码如下:

代码语言:java
复制
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!");
}

42. 检查null引用,并抛出特定异常

问题:检查null引用,并抛出特定异常。

思路:使用if检查,然后抛出异常。

43. 检查null引用,并设置默认值

问题:检查null饮用,并在为null的时候设置默认值。

思路:使用if检查,并设置默认值,或使用Objects.requireNonNullElseGet

代码如下:

代码语言:java
复制
public void nullTestSetDefaultValue() {
    String name = null;
    if (name == null) {
        name = "default name";
    }
    // 等价于if (name == null) name = ...
    name = Objects.requireNonNullElse(name, "default name");
}

44. 检查索引范围是否在[0, length)范围内

问题:检查给定索引是否在[0, length)范围内。

思路:使用Objects.checkIndex检查(JDK9)。

45. 检查索引段是否在[0, length)范围内

问题:检查索引段是否在[0, length)范围内。

思路:使用Objects.checkFromToIndex检查(JDK9)。

46. 说明equalshashCode如何工作

问题:说明equalshashCode在java中如何工作

思路:说明。

用途说明:

equalshashCode是每个类都有的方法。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,不相等。 代码如下:
代码语言:java
复制
@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实现需要满足:

  • 两个相等的对象,必须返回相同的hash code。
  • 只要对象不发生改变,必须返回相同的hash code。 因此:
  • 当重写equals方法,必须重写hashCode方法。
  • 在两个方法中必须使用相同的属性集。

47. 解释不可变对象

问题:解释不可变对象。

思路:说明。

  • 基本类型是不可变的。
  • 一些常用类,比如StringPatternLocalDate是不可变的。
  • 数组是不可变的。
  • Collections可以是可变的,不可修改的,或不可变的。 不可变对象在多线程环境中常用,因为它不会引起并发中的一些常见问题。

48. 不可变字符串

问题:字符串是不可变的,这样设计有什么好处?

思路:说明。

不可变的优势

字符串常量池:

在创建字符串常量时,所有的字符串常量会被保存在字符串常量池中,代码如下:

代码语言:java
复制
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缓存:

可以缓存hash code。

不可变的缺点

无法继承

无法通过继承为String添加更多功能。

安全问题

如果通过String保存敏感数据,那这些数据可能长时间存在于字符串常量池中,存在安全隐患。

内存溢出

字符串常量池不大,可能导致内存溢出错误。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 40. 函数式和过程式的判空
  • 41. 检查null引用,并抛出自定义NullPointerException
  • 42. 检查null引用,并抛出特定异常
  • 43. 检查null引用,并设置默认值
  • 44. 检查索引范围是否在[0, length)范围内
  • 45. 检查索引段是否在[0, length)范围内
  • 46. 说明equals和hashCode如何工作
    • 用途说明:
      • 默认实现:
        • 重写实现
        • 47. 解释不可变对象
        • 48. 不可变字符串
          • 不可变的优势
            • 字符串常量池:
            • 安全:
            • 线程安全:
            • hash code缓存:
          • 不可变的缺点
            • 无法继承
            • 安全问题
            • 内存溢出
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档