【问题标题】:When to use primitive and when reference types in Java在 Java 中何时使用原始类型以及何时使用引用类型
【发布时间】:2010-03-24 15:38:41
【问题描述】:

在哪种情况下应该使用原始类型(int)或引用类型(Integer)?

这个question激发了我的好奇心。

【问题讨论】:

    标签: java primitive-types reference-type


    【解决方案1】:

    由于 Java 做了一些称为 auto-boxing and auto-unboxing 的操作,因此在大多数情况下,您应该使用基本类型 int,因为开销较小。

    您绝对需要使用 Integer 的唯一情况是在泛型中。

    List<int> list; // won't compile
    List<Integer> list; // correct
    

    【讨论】:

    • 好吧,当尝试在需要对象的地方使用原始类型时。
    【解决方案2】:

    可能首选Integer 的一种情况是,当您使用允许数字条目为空的数据库时,因为您无法用int 表示空值。

    但当然,如果你是在做直接的数学运算,那么 int 会更好,因为其他人提到的因为直观性和开销更少。

    【讨论】:

      【解决方案3】:

      在什么情况下你应该使用原语 类型(int)或引用类型 (Integer)?

      根据经验,我将使用原语(例如int),除非我必须使用包装原语的类。

      其中一种情况是必须使用包装类,例如Integer,在使用generics 的情况下,因为Java 不支持使用原始类型作为类型参数:

      List<int> intList = new ArrayList<int>();               // Not allowed.
      List<Integer> integerList = new ArrayList<Integer>();   // Allowed.
      

      而且,在很多情况下,我将利用autoboxing and unboxing,因此我不必显式执行从原语到其包装类的转换,反之亦然:

      // Autoboxing will turn "1", "2", "3" into Integers from ints.
      List<Integer> numbers = Arrays.asList(1, 2, 3); 
      
      int sum = 0;
      
      // Integers from the "numbers" List is unboxed into ints.
      for (int number : numbers) {
        sum += number;
      }
      

      另外,作为附加说明,当从基元转换为其包装类对象时,对象的唯一实例不是必需的,请使用包装方法提供的valueOf 方法,因为它执行缓存并返回相同的实例对于某个值,减少创建的对象数量:

      Integer i1 = Integer.valueOf(1);   // Prefer this.
      Integer i2 = new Integer(1);       // Avoid if not necessary.
      

      有关valueOf 方法的更多信息,Integer.valueOf 方法的 API 规范可以作为这些方法在基元包装类中的行为方式的参考。

      【讨论】:

        【解决方案4】:

        我在创建 API 时遵循的一般规则可以总结如下:

        1. 如果方法必须返回值,请使用原始类型
        2. 如果该方法可能并不总是适用(例如:getRadioId(...) 对可能不存在此类 ID 的对象),则返回一个整数并在 JavaDocs 中指定该方法在某些情况下将返回 null。

        在 #2 上,自动装箱时注意 NPE。如果你有一个方法定义为:

        public Integer getValue();
        

        然后调用如下:

        int myValue = getValue();
        

        在 getValue() 返回 null 的情况下,您将在没有明显原因的情况下获得 NPE。

        【讨论】:

          【解决方案5】:

          这真的取决于上下文。首先更喜欢原语,因为它更直观且开销更少。如果由于泛型/自动装箱原因而无法实现,或者如果您希望它可以为空,则选择包装器类型(您称之为复杂类型)。

          【讨论】:

          • 另外需要考虑的一点是是否需要区分无值(null)和零。
          【解决方案6】:

          我的经验法则是:仅在需要编译代码时才使用盒装原语。原始包装类的名称应该出现在代码中的唯一位置是泛型类型参数和静态方法调用:

          List<Integer> intList = new ArrayList<Integer>();
          
          int n = Integer.parseInt("123");
          

          这就是我要给新的 Java 程序员的建议。随着他们了解得越多,他们就会遇到必须更具洞察力的情况,例如在处理地图或数据库时,但到那时他们也应该更好地了解图元和盒装图元之间的区别。

          自动装箱让我们相信intInteger(例如)可以互换,但这是一个陷阱。如果您不加选择地混合这两种值,您最终可能会将两个整数值与== 进行比较,或者试图在没有意识到的情况下将null 拆箱。由此产生的错误可能是间歇性的,难以追踪。

          将盒装图元与== 进行比较没有帮助有时 就像在进行值比较一样。这是在自动装箱过程中自动缓存一定范围内的值造成的错觉。这与我们在使用 String 值时一直遇到的问题相同:将它们与 == 进行比较有时“有效”,因为您实际上是在比较同一个缓存对象的两个引用。

          在处理字符串时,我们可以告诉 n00bs 永远不要将它们与== 进行比较,就像我们一直在做的那样。但是将原语与== 进行比较是完全有效的;诀窍(感谢自动装箱)是确保这些值确实是原语。编译器现在让我们将变量声明为Integer 并像使用int 一样使用它;这意味着我们必须加强纪律,并在有人无故这样做时将其视为错误。

          【讨论】:

            【解决方案7】:

            与其称它们为“复杂类型”,不如将 Integer、Double 等视为“类”,将 int、double 等视为“原始类型”。

            如果您要进行任何类型的复杂数学运算,Integer 和 Double 等基于类的数​​字表示会很麻烦并且会减慢您的速度 - 许多数学运算只能使用基元来完成。

            另一方面,如果您尝试将数字放入 Lists 和 Maps 等集合中,这些集合只能包含对象 - 因此您必须使用(或转换为)Integer 和 Double 等类。

            就我个人而言,只要我能摆脱它,我就会使用原语,并且只在需要进行输入或输出时转换为 Integer 等类表示,并且传输需要这些表示。

            但是,如果您根本不做任何数学运算,而只是直接通过代码传递值,则可以通过专门处理基于类的表单(如整数)来省去一些麻烦。

            【讨论】:

              【解决方案8】:

              我认为没有这样的规则。当我编写方法签名、映射、集合、传递的数据对象时,我会选择类型而不是原始类型(整数而不是 int)。因此,即使在方法等内部,我仍然想使用 Integer 而不是 int。但是如果您认为这太麻烦(输入额外的“eger”),那么可以将 int 用于局部变量。

              【讨论】:

                【解决方案9】:

                如果你想在会话中设置属性,你必须在 servlet 中使用像 Integer、Boolean、String 这样的对象。如果你想使用值,你可以使用原始类型。对象可能为空,但原语不是。如果您想比较基元的类型,请使用 == 但对象使用 .equals 因为在对象比较中 == 看起来不是值,它看起来是否是相同的对象。使用原语可以加快代码速度。

                【讨论】:

                  【解决方案10】:

                  我认为这有点晚了,但我想补充一下我的意见以防万一。

                  在某些情况下,需要使用包装器,因为缺少值与默认值不同。

                  例如, 对于我从事的一个项目,屏幕上有一个字段,用户可以在其中输入双精度值,业务需求明确提到,如果用户输入 0,则含义与不输入值并将字段留空不同,这差异将在以后在不同的模块中产生影响。 所以在这种情况下,我们必须使用 Double 对象,因为我不能使用原语来表示缺乏价值;因为原语将默认为 0,这是该字段的有效输入。

                  【讨论】:

                    【解决方案11】:

                    当我们处理 Spring getRequest 映射方法时,使用布尔值是行不通的。

                    例如:

                    @GetMapping("/goal")
                    public boolean isValidGoal() { 
                        boolean isValid = true;
                        return isValid;
                    }
                    

                    在这些情况下总是选择布尔值。

                    【讨论】:

                      猜你喜欢
                      • 2010-12-06
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2011-01-25
                      • 1970-01-01
                      • 2014-07-07
                      相关资源
                      最近更新 更多