简体   繁体   English

是创建一个仅在Optional.ifPresentOrElse中使用的类变量,以避免这种做法吗?

[英]is create a class variable just to be used in Optional.ifPresentOrElse a practice to be avoid?

In few words my context is: call an API and if I find certain header variable I subString it to return a value. 简而言之,我的上下文是:调用一个API,如果我发现某些标头变量,则将其subString返回一个值。 If not I must return the Response.status. 如果没有,我必须返回Response.status。 I have successfully reached such requirement with this code: 我已经通过以下代码成功达到了这样的要求:

...
import com.mashape.unirest.*
...
@Controller
public class MainController {
    private final String gmailKey = "XXX";

    private String stringRetorno = "0";

    @ResponseBody
    @GetMapping("/getsessionkey")
    public String getSessionKey() {

        try {

            HttpResponse<String> response = Unirest
                    .post("https://skyscanner-skyscanner-flight-search-v1.p.rapidapi.com/apiservices/pricing/v1.0")
                    .header("x-rapidapi-host", "skyscanner-skyscanner-flight-search-v1.p.rapidapi.com")
                    .header("x-rapidapi-key", gmailKey).header("Content-Type", "application/x-www-form-urlencoded")

                    .body("inboundDate=2019-11-25&cabinClass=economy&children=0&infants=0&Country=BR&Currency=BRL&locale=pt-BR&originPlace=GRU-sky&destinationPlace=MCZ-sky&outboundDate=2019-11-19&adults=2")
                    .asString();

            Optional<String> optionalLocation = Optional.ofNullable(response.getHeaders().getFirst("Location"));

            optionalLocation.ifPresentOrElse(l -> stringRetorno = l.substring(l.lastIndexOf("/") + 1),
                    () -> stringRetorno = String.valueOf(response.getStatus()));

        } catch (Exception e) {
            e.printStackTrace();
        }

        return stringRetorno;

    }

My doubt relies in how properly I coded it. 我的疑问取决于编码的方式。 Instead of coding a chain of if&null I decided to use a more elegant and readble way with Optional. 我决定不使用if&null链,而是选择使用一种更优雅,更易读的方式与Optional配合使用。 But I faced "Local variable stringRetorno defined in an enclosing scope must be final or effectively final" if I create stringRetorno inside of the method. 但是,如果我在方法内部创建stringRetorno,则会遇到“在封闭范围内定义的局部变量stringRetorno必须是最终的或实际上是最终的”。

Searching around I found as solution create stringRetorno as class variable. 搜索周围,我发现作为解决方案创建stringRetorno作为类变量。

So my straigh question is: am I doing something to be avoid? 所以我的直截了当的问题是:我正在做一些事情要避免吗? Some questions that may not answer my question but be very usefull are: 一些可能无法回答我的问题但非常有用的问题是:

  • should I prefer other Java HTTP Client than com.mashape.unirest which may already provide Optional so I would be able to write less verbose code? 我是否应该比com.mashape.unirest更喜欢其他Java HTTP Client,而com.mashape.unirest可能已经提供了Optional,所以我可以编写更少的详细代码? I don't want to compare libraries at all. 我根本不想比较库。 My focus is coupling with the possibility to receive a response header missing a specific key (location). 我的重点是结合接收缺少特定键(位置)的响应头的可能性。 And if the lightweight unirest suggested by the API Provider forces me to workarounds maybe a suggestion of another library that provides Optional as answer should help me. 而且,如果API提供程序建议的轻量级Unirest迫使我采取变通办法,则可能是另一个提供Optional的库的建议也可以帮助我。

  • isn't overwhelming writing Optional inside of Try/Catch block? 难道不是在Try / Catch块内编写Optional的?

*** Solution ***解决方案

thanks to answers provided 感谢提供的答案

@ResponseBody
@GetMapping("/getsessionkey")
public String getSessionKey() {

    Optional<String> optionalLocation = null;
    HttpResponse<String> response = null;
    try {

        response = Unirest
                .post("https://skyscanner-skyscanner-flight-search-v1.p.rapidapi.com/apiservices/pricing/v1.0")
                .header("x-rapidapi-host", "skyscanner-skyscanner-flight-search-v1.p.rapidapi.com")
                .header("x-rapidapi-key", gmailKey).header("Content-Type", "application/x-www-form-urlencoded")

                .body("inboundDate=2019-11-25&cabinClass=economy&children=0&infants=0&Country=BR&Currency=BRL&locale=pt-BR&originPlace=GRU-sky&destinationPlace=MCZ-sky&outboundDate=2019-11-19&adults=2")
                .asString();

        optionalLocation = Optional.ofNullable(response.getHeaders().getFirst("Location"));

    } catch (Exception e) {
        e.printStackTrace();
    }

    return optionalLocation.map(l -> l.substring(l.lastIndexOf("/") + 1))
            .orElse(String.valueOf(response.getStatus()));

}

ifPresentOrElse is probably not the method you want to use, but rather .orElse . ifPresentOrElse可能不是您要使用的方法,而是.orElse

return optionalLocation.orElse(String.valueOf(response.getStatus()));

You would want to use ifPresentOrElse if there is some action you want to take, like logging, when the optional is empty. 如果可选选项为空,则如果要执行某些操作(例如记录),则需要使用ifPresentOrElse

am I doing something to be avoid? 我在做避免的事情吗?

Yes. 是。 It is poor form to pull the variable outside the only method to which it is relevant. 将变量拉到与其相关的唯一方法之外的形式很差。 Moreover, as a practical matter, it creates a thread-safety problem for you -- as currently written, a program that uses your class and allows two different threads to invoke MainController.getSessionKey() is for that reason likely to not be properly synchronized. 而且,实际上,它为您创建了一个线程安全问题-如当前编写的那样,一个使用您的类并允许两个不同的线程调用MainController.getSessionKey()程序由于这个原因很可能无法正确同步。 。 The same would not be true if it were a local variable of the method. 如果它是方法的局部变量,那将是不正确的。

You can use a variable that is local to the method if it is a mutable container for your string (an array, List , or AtomicReference , for example). 如果该变量是字符串的可变容器 (例如,数组, ListAtomicReference ),则可以使用该方法本地的变量。 Then the container can be final or effectively final, without preventing you from changing its contents. 然后,容器可以是最终容器,也可以是有效的最终容器,而不会阻止您更改其内容。

But it would be cleaner to use a combination of map() and orElse() so that you don't need to set the string reference with a lambda in the first place: 但是使用map()orElse()的组合会更清洁,这样您就不需要首先使用lambda来设置字符串引用:

stringRetorno = optionalLocation.map(l -> l.substring(l.lastIndexOf("/") + 1))
        .orElse(String.valueOf(response.getStatus()));
  • should I prefer other Java HTTP Client than com.mashape.unirest which may already provide Optional so I would be able to write less verbose code? 我是否应该比com.mashape.unirest更喜欢其他Java HTTP Client,而com.mashape.unirest可能已经提供了Optional,所以我可以编写更少的详细代码?

Perhaps I misunderstand, but the only code savings I see from that is removing the Optional.ofNullable() invocation (but keeping an equivalent of its argument). 也许我误会了,但是我看到的唯一节省代码的地方是删除了Optional.ofNullable()调用(但保留了其参数的等效项)。 That's not much reduction in verbosity, nor much, if any, improvement in clarity. 这并不是冗长的减少,也不是清晰度的改善。 I wouldn't consider the potential to do that to be any reason to look for a different client. 我认为这样做的潜力不是寻找其他客户的任何理由。

(But if you do look for a different client, don't look here . Recommendations for libraries and other off-site resources are off-topic here.) (但是,如果您确实要寻找其他客户端,请不要在这里查看 。有关图书馆和其他场外资源的建议在这里不合时宜。)

  • isn't overwhelming writing Optional inside of Try/Catch block? 难道不是在Try / Catch块内编写Optional的?

Um, no? 不? Maybe "overwhelming" isn't the term you're looking for, but even if you really mean "overkill" or "excessive" or similar, then still no. 也许“压倒性”不是您要查找的术语,但是即使您确实是“过分杀伤”或“过量”或类似的意思,也仍然没有。 I'm not really even seeing why you suppose it might be so. 我什至看不到你为什么会这样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 选修的<integer>空时从 Optional.ifPresentOrElse() 返回一个字符串?</integer> - Optional<Integer> return a string from Optional.ifPresentOrElse() when empty? Java 8 中 Optional 的 ifPresentOrElse 的奇怪行为(对我而言) - Strange behaviour (for me) with ifPresentOrElse of an Optional in Java 8 如何使用 Optional 的 ifPresentOrElse 返回 boolean 值? - How can I return a boolean value with Optional's ifPresentOrElse? 使用 Java 可选 ifPresentOrElse 方法时无法抛出 `checked` 异常 - Unable to throw a `checked` exception when using Java Optional ifPresentOrElse method 如何创建一个包含意图使用类的变量 - How can I create a variable that contain class to be used in intent 用Class <?替换Class是一种好习惯吗?扩展Object>以避免警告? - Is it good practice to replace Class with Class<? extends Object> to avoid warnings? 仅在课堂上使用的公共方法的警告 - Warning for public method used just in class 在该类中创建类的实例是标准做法吗? - Is it standard practice create an instance of a class within that class? 我应该避免使用常用的类名吗? - Should I avoid commonly used class names? 仅通过其唯一的instanceID来使equal()类实例不好吗? - Is it bad practice to equal() class instances by just their unique instanceID?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM