欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java?Optional的判空操作詳解

 更新時間:2022年09月30日 16:47:08   作者:Java面試365  
JAVA在1.8版本推出Optional,官方文檔將其描述為可能包含或不包含非空值的容器對象,目前Optional用于避免程序出現(xiàn)異常NullPointerException,感興趣的可以了解一下

Optional判空

JAVA在1.8版本推出Optional,官方文檔將其描述為可能包含或不包含非空值的容器對象,目前Optional用于避免程序出現(xiàn)異常NullPointerException。

代碼模擬

// 下面所有類省略set,get方法
public class Employee {
    private String employeeName;
    private Team team;
}

public class Team {
    private String teamName;
    private Department department;

    public Team(String teamName) {
        this.teamName = teamName;
    }
}

public class Department {
    private String departmentName;
    private Company company;
}

public class Company {
    private String companyName;
}

測試代碼

// 在創(chuàng)建時因為沒有初始化Team對象的Department屬性,導(dǎo)致后續(xù)調(diào)用空指針
public void testCompany(){
    Employee employee = new Employee();
    employee.setEmployeeName("zhangsan");
    employee.setTeam(new Team("xxx產(chǎn)品組"));
    System.out.println(employee.getTeam().getDepartment().getCompany().getCompanyName());
}

這時如果我們采用傳統(tǒng)方式一般判空代碼如下

public void testCompanyAvoidNPE(){
    Employee employee = new Employee();
    employee.setEmployeeName("zhangsan");
    employee.setTeam(new Team("xxx產(chǎn)品組"));
    Team team = employee.getTeam();
    if (team == null){
        System.out.println("異常拉,參數(shù)為空!");
        return;
    }
    Department department = team.getDepartment();
    if (department == null){
        System.out.println("異常拉,參數(shù)為空!");
        return;
    }
    Company company = department.getCompany();
    if (company == null){
        System.out.println("異常拉,參數(shù)為空!");
        return;
    }
    String companyName = company.getCompanyName();
    System.out.println(companyName);
}

顯然這種判空代碼造成了業(yè)務(wù)代碼膨脹,代碼可讀性極低,所以在這種場景下我們需要學(xué)習(xí)1.8推出的判空容器對象Optional。

Optional常用方法

創(chuàng)建 Optional 對象

JAVA提供了三個靜態(tài)方法用于構(gòu)建Optional對象如下所示

返回值方法和描述
static <T> Optional<T>empty()  返回一個空的 Optional實例。
static <T> Optional<T>of(T value)  返回具有 Optional的當前非空值的Optional。
static <T> Optional<T>ofNullable(T value)  返回一個 Optional指定值的Optional,如果非空,則返回一個空的  Optional 。
public void createOptionalObject(){
    System.out.println(Optional.empty());
    // 傳null報空指針
    // System.out.println(Optional.of(null));
    System.out.println(Optional.of(new String("1111")));
    // 傳null調(diào)用Optional.empty()
    System.out.println(Optional.ofNullable(null));
    System.out.println(Optional.ofNullable(new Content("111","測試內(nèi)容")));
}

class Content {
    private String id;
    private String value;

    public Content() {
    }

    public Content(String id, String value) {
        this.id = id;
        this.value = value;
    }
    // 省略get,set方法
}

執(zhí)行結(jié)果如下

Optional.empty
Optional[1111]
Optional.empty
Optional[Content{id='111', value='測試內(nèi)容'}]

在真正使用時建議使用ofNullable,因為它能處理空值或者非空值,代碼如下

public static <T> Optional<T> ofNullable(T value) {
    return value == null ? empty() : of(value);
}

常用功能方法

方法名返回值功能描述
isPresent()boolean判斷Optional對象是否存在,存在true不存在false
ifPresent(Consumer<? super T> consumer)void如果Optional對象存在執(zhí)行consumer消費型接口,不存在不執(zhí)行
getT返回Optional對象封裝的對象T數(shù)據(jù),注意實際對象可能為空會拋出異常
orElse(T other)T如果Optional對象存在則返回封裝的對象數(shù)據(jù),如果不存在返回T other數(shù)據(jù),相當于不存在給默認值
orElseGet(Supplier<? extends T> other)T是orElse方法的升級版,區(qū)別在于orElse方法傳入的是一個固定默認值,而此方法是一個供給型函數(shù)方法,如果Optional對象為空則執(zhí)行other的方法邏輯
orElseThrow(Supplier<? extends X> exceptionSupplier)<X extends Throwable>T一樣是orElse方法的升級版,當Optional對象為空執(zhí)行exceptionSupplier方法,最后拋出異常
filter(Predicate<? super T> predicate)Optional<T>當Optional對象滿足predicate斷言函數(shù)中的匹配規(guī)則則返回,否則返回空Optional
map(Function<? super T,? extends U> mapper)<U> Optional<U>能夠?qū)ptional的對象值處理轉(zhuǎn)換為另一個實例對象值,并生成新類型的Optional對象,如果生成的新對象為null,則返回一個空Optional對象
flatMap(Function<? super T,Optional<U>> mapper)<U> Optional<U>和map類似,不過map操作的是具體對象,而flatMap返回的是Optional封裝過的對象

代碼演示如下

    public void testOptionFunction(){
        //===============================isPresent()================================
        // false
        System.out.println(Optional.empty().isPresent());
        // Optional[Content{id='222', value='測試'}]
        System.out.println(Optional.ofNullable(new Content("222","測試")));

        //===============================ifPresent()================================
        // 不為空打?。篊ontent{id='222', value='測試'}  為空不執(zhí)行
        Optional.ofNullable(new Content("222","測試")).ifPresent(e->{
            System.out.println("不為空打?。?+e);
        });

        //===============================get()================================
        // NoSuchElementException: No value present
        try {
            System.out.println(Optional.empty().get());
        }catch (Exception e){
            e.printStackTrace();
        }
        // Content{id='222', value='測試'}
        System.out.println(Optional.ofNullable(new Content("222","測試")).get());

        //===============================orElse()================================
        // Content{id='0', value='默認'}
        System.out.println(Optional.empty().orElse(new Content("0","默認")));

        //===============================orElseGet()================================
        // Content{id='333', value='測試orElseGet'}
        System.out.println(Optional.empty().orElseGet(() -> {
            Content content = new Content("333", "測試orElseGet");
            return content;
        }));

        // Content{id='222', value='測試'}
        System.out.println(Optional.ofNullable(new Content("222", "測試")).orElseGet(() -> {
            Content content = new Content("444", "測試orElseGet");
            return content;
        }));

        //===============================orElseThrow()================================
        // java.lang.Exception: 參數(shù)為空
        try {
            Optional.empty().orElseThrow(()->{
               return new Exception("參數(shù)為空");
            });
        } catch (Exception e) {
            e.printStackTrace();
        }

        //===============================filter()================================
        // "555".equals(e.getId());   Optional[Content{id='555', value='測試'}]
        // "5565".equals(e.getId());  Optional.empty
        System.out.println(Optional.ofNullable(new Content("555", "測試")).filter(e -> {
            return "5565".equals(e.getId());
        }));
    }

map和flatMap

public void testOptionMapFunction(){
    Optional<Content> optionalContent = Optional.ofNullable(new Content("777","測試Map"));

    Optional<Content> optionalContent1 = optionalContent.map(e -> {
        String id = e.getId();
        String value = e.getValue();
        return e;
    });

    Optional<Content> optionalContent2 = optionalContent.flatMap(e -> {
        String id = e.getId();
        String value = e.getValue();
        // 不同點在這里,一個是可以轉(zhuǎn)換為另一個實例對象,一個是轉(zhuǎn)換為Optional包裝對象
        return Optional.of(e);
    });
    // 最終效果實現(xiàn)效果類似
    System.out.println(optionalContent1);
    System.out.println(optionalContent2);
}

使用Optional一定比null好嗎

這個顯然是不對的,如果使用方式如下所示,其實和null的直接判空沒有區(qū)別

public static void main(String[] args) {
    Optional<Content> optionalContent = Optional.ofNullable(null);
    // 直接報錯
    optionalContent.get();
}

// 升級寫法
public static void main(String[] args) {
    Optional<Content> optionalContent = Optional.ofNullable(null);
    // 非空判斷
    if (optionalContent.isPresent()){
        System.out.println(optionalContent.get());
    }
}

null的直接判空

public static void main(String[] args) {
    Content content = new Content();
    if (content != null){
        System.out.println(content);
    }
}

正確寫法如下所示

public static void main(String[] args) {
    Optional<Content> optionalContent = Optional.ofNullable(null);
    // 非空時執(zhí)行消費型接口里面的邏輯
    optionalContent.ifPresent(content -> {
        System.out.println(content);
    });
}

到這里有人可能說,如果if{}else{}里面都需要寫邏輯如何處理呢

public static void main(String[] args) {
    Optional<Content> optionalContent = Optional.ofNullable(null);
    Content content = optionalContent.map(e -> {
        // 做一些業(yè)務(wù)
        // 返回值可以為任意類型值,可以返回字符串,不過orElseGet需要返回字符串保持一致即可
        return e;
    }).orElseGet(() -> {
        // 做一些業(yè)務(wù)
        return new Content("0", "默認值");
    });
    System.out.println(content);
}

Optional 使用場景

減少繁瑣的非空判斷

如前面提到的testCompanyAvoidNPE方法中的例子,就可以采用Optional來簡化

public void testCompanyAvoidNPE2(){
    Employee employee = new Employee();
    employee.setEmployeeName("zhangsan");
    employee.setTeam(new Team("xxx產(chǎn)品組"));
    // 這里相當于是鏈式操作
    String companyName = Optional.ofNullable(employee)
        .map(employee1 -> employee1.getTeam())
        .map(team -> team.getDepartment())
        .map(department -> department.getCompany())
        .map(company -> company.getCompanyName())
        .orElse("no company");
    System.out.println(companyName);
}

設(shè)置默認值兜底

// 原始方法
public String setDefaultValue1(Content content){
    if (ObjectUtils.isEmpty(content)){
        return "0";
    }
    if (StringUtils.isEmpty(content.getId())){
        String id = "0";
        content.setId(id);
    }
    return content.getId();
}

// 采用Optional
public String setDefaultValue2(Content content){
    String id = Optional.ofNullable(content)
        .map(content1 -> content1.getId())
        .orElse("0");
    return id;
}

Optional 盡量只用作方法的返回類型

注意我們采用Optional的最終目的是避免程序中出現(xiàn)null對象異常的情況,所以我們封裝方法的時候可以采用Optional 作為方法的返回值類型,但也要注意Optional雖好但不要濫用,適當使用即可。

以上就是Java Optional的判空操作詳解的詳細內(nèi)容,更多關(guān)于Java Optional判空操作的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論