为什么我在这里得到一个空值?

问题描述 投票:0回答:1

所以这段代码

  public boolean getOppositePriceConversion(Integer catalogId) {
    return Optional.of(catalogStore.getCatalog(catalogId))
        .map(CatalogDO::getOppositePriceConversion)
        .orElse(Boolean.FALSE);}

返回 null,而这个则不返回

 public boolean getOppositePriceConversion(Integer catalogId) {
    CatalogDO catalog = catalogStore.getCatalog(catalogId);
    if (catalog != null) {
      Boolean oppositeConversion = catalog.getOppositePriceConversion();
      return oppositeConversion != null ? oppositeConversion : false;
    }
    return false;
  }

为什么会发生这种情况?我认为可选链可以处理空值。

java nullreferenceexception optional-chaining
1个回答
0
投票

正如@Chaosfire所说,你的

getOppositePriceConversion(Integer catalogId)
不可能返回null,所以如果你的意思是
catalogStore.getCatalog
抛出一个
NullPointerException
,你可以通过
Optional.ofNullable
来处理它。我对此非常确定,我喜欢创建一些关于它的测试用例,这是玩 Mokito 的一个很好的借口!

鉴于该结构:

package org.example;

import java.util.Optional;

public class OptionalNull {
    public static class CatalogService {
        private final CatalogStore catalogStore;

        public CatalogService(CatalogStore catalogStore) {
            this.catalogStore = catalogStore;
        }

        public boolean getOppositePriceConversion(Integer catalogId) {
            return Optional.of(catalogStore.getCatalog(catalogId))
                    .map(CatalogDO::oppositePriceConversion)
                    .orElse(Boolean.FALSE);
        }
        public boolean getOppositePriceConversionOfNullable(Integer catalogId) {
            return Optional.ofNullable(catalogStore.getCatalog(catalogId))
                    .map(CatalogDO::oppositePriceConversion)
                    .orElse(Boolean.FALSE);
        }
    }

    public interface CatalogStore {
        CatalogDO getCatalog(Integer catalogId);
    }

    public record CatalogDO(Integer id, Boolean oppositePriceConversion) {}
}

然后是测试:

package org.example.test;

import org.example.OptionalNull;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.example.OptionalNull.*;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class OptionalNullTest {
    @Mock
    private CatalogStore catalogStore;
    private CatalogService optionalNull;

    @BeforeEach
    void setUp() {
        optionalNull = new CatalogService(catalogStore);

        when(catalogStore.getCatalog(1)).thenReturn(null);
        when(catalogStore.getCatalog(2)).thenReturn(new CatalogDO(2, true));
        when(catalogStore.getCatalog(3)).thenReturn(new CatalogDO(3, false));
    }

    @Test
    void getOppositePriceConversionOfNullable() {
        assertThat(optionalNull.getOppositePriceConversionOfNullable(1))
                .isFalse();

        assertThat(optionalNull.getOppositePriceConversionOfNullable(2))
                .isTrue();

        assertThat(optionalNull.getOppositePriceConversionOfNullable(3))
                .isFalse();
    }

    @Test
    void getOppositePriceConversion() {
        assertThatThrownBy(() -> optionalNull.getOppositePriceConversion(1))
                .isExactlyInstanceOf(NullPointerException.class)
                .hasNoCause();

        assertThat(optionalNull.getOppositePriceConversion(2))
                .isTrue();

        assertThat(optionalNull.getOppositePriceConversion(3))
                .isFalse();
    }
}

仅供参考:java 17、junit 5.10.1、assterj 3.25.1、mokito 5.2.0

© www.soinside.com 2019 - 2024. All rights reserved.