Objects.requireNonNull使用的多种使用情形和案例

案例有3中情形使用Objects.requireNonNull

  1. 第1种情形有2种,都是直接复制,一个通过构造函数,一个通过设置函数
  2. 第2中情形是验证的引用没有调用,但是不过不验证,再之后调用对象方法会导致空指针异常,无法查询空指针的赋值点。
  3. 第3种情形是虽然对引用调用有函数调用,会导致异常,感觉可以不用验证。但是可能导致对象状态的修改。但调用是失败的。
package org.ziegler.javabase.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class RequiredNonNullSample {

    private Ball ball;

    private List<Ball> ballBucket = new ArrayList<>();

    RequiredNonNullSample(Ball ball) {
        // 情形1.1:赋值的第一时间验证。使用时验证,不容易查询空引用异常
        this.ball = Objects.requireNonNull(ball);
    }

    void setBall(Ball ball) {
        // 情形1.2:赋值的第一时间验证。使用时验证,不容易查询空引用异常
        this.ball = Objects.requireNonNull(ball);
    }

    void addBall(Ball ball) {
        // 情形2:第一时间验证对象是否为{@code null}
        Objects.requireNonNull(ball, "ball is null");

        ballBucket.add(ball);
    }

    void showBallBucket() {
        ballBucket.forEach(Ball::printBall);
    }

    /**
     * 将2个{@link Ball}的尺寸都设置为相同值{@code size}
     * @param ball1 不能为{@code null}
     * @param ball2 不能为{@code null}
     * @param size
     * @throws NullPointerException 参数为{@code ball1 == null}或者{@code ball2 == null}
     */
    public static void setBallSameSize(Ball ball1, Ball ball2, int size) {
        /**
         * 情形3:
         * 这种调用方式如果不调用Objects.requireNonNull,是不是也可以呢?
         * 因为调用Ball对象的{@link Ball#setSize(int)} ()}方法也会抛出异常。
         * 但是如果{@code ball2 == null}那么会导致ball1的状态改变,但是调用
         * {@code ball2.setSize(size);}抛出异常
         * 没能达到这个函数的要求,同时设置2个球的size,只改变了第一个Ball的尺寸,
         * 并且在发生异常之后,没能回滚操作。但通过Objects.requireNonNull验证就可以避免。
         * 总结:前置的Objects.requireNonNull验证,防止破坏对象状态,在第一时间发现异常。
         */
        Objects.requireNonNull(ball1, "ball1 is null");
        Objects.requireNonNull(ball2, "ball2 is null");

        ball1.setSize(size);
        ball2.setSize(size);
    }

    /**
     * 上面方法的错误写法
     * @param ball1
     * @param ball2
     * @param size
     */
    @Deprecated
    public static void setBallSameSizeDeprecated(Ball ball1, Ball ball2, int size) {
        /**
         * 这种调用方式如果不调用Objects.requireNonNull,是不是也可以呢?
         * 因为调用Ball对象的{@link Ball#setSize(int)} ()}方法也会抛出异常。
         * 但是如果{@code ball2 == null}那么会导致ball1的状态改变,但是调用
         * {@code ball2.setSize(size);}抛出异常
         * 没能达到这个函数的要求,同时设置2个球的size,只改变了第一个Ball的尺寸,
         * 并且在发生异常之后,没能回滚操作。但通过Objects.requireNonNull验证就可以避免。
         */

        ball1.setSize(size);
        ball2.setSize(size);
    }

    public void printBall() {
        // 因为在引用赋值的时候已经验证了ball有效,所以调用可以不验证
        ball.printBall();
    }

    public static class Ball {

        private int size;

        public Ball(int size) {
            this.size = size;
        }

        public int getSize() {
            return size;
        }

        public void setSize(int size) {
            this.size = size;
        }

        public void printBall() {
            System.out.println("ball - size = " + getSize());
        }

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder("Ball{");
            sb.append("size=").append(size);
            sb.append('}');
            return sb.toString();
        }

    }

    public static void main(String[] args) {
        Ball defaultBall = new Ball(8);
        Ball ball1 = new Ball(5);
        Ball ball2 = new Ball(11);

        RequiredNonNullSample requiredNonNullSample = new RequiredNonNullSample(defaultBall);
        requiredNonNullSample.printBall();

        requiredNonNullSample.setBall(ball1);
        requiredNonNullSample.printBall();

        requiredNonNullSample.addBall(ball1);
        requiredNonNullSample.addBall(ball2);
        requiredNonNullSample.showBallBucket();

        setBallSameSizeTest();

        setBallSameSizeDeprecatedTest();
    }

    static void setBallSameSizeTest() {
        Ball ballA = new Ball(5);
        Ball ballB = null;

        try {
            setBallSameSize(ballA, ballB, 10);
        } catch (RuntimeException e) {
            System.out.println("e = " + e);
        }

        ballA.printBall();
    }

    static void setBallSameSizeDeprecatedTest() {
        Ball ballA = new Ball(5);
        Ball ballB = null;

        try {
            setBallSameSizeDeprecated(ballA, ballB, 10);
        } catch (RuntimeException e) {
            System.out.println("e = " + e);
        }

        ballA.printBall();
    }

}

输出结果:

ball - size = 8
ball - size = 5
ball - size = 5
ball - size = 11
e = java.lang.NullPointerException: ball2 is null
ball - size = 5
e = java.lang.NullPointerException
ball - size = 10

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值