当前位置: 首页 > 知识库问答 >
问题:

Integer类如何在不调用字段或方法的情况下直接存储值[重复]

曹镜
2023-03-14

示例:

Integer x = 56; 

正如我所理解的,只有在调用类或方法中的字段时,值才能存储在对象中。在<code>Integer</code>类的情况下,如果不实例化对象,它不应该能够调用其值字段,因为值不是静态的。这怎么可能?

共有2个答案

杭涵映
2023-03-14

语言可以并且确实为语言中内置的对象类型做任何它想要的异常。简而言之,你可以在Java做到这一点,因为Java说你可以。

具体来说,将原始值(int、Long等)转换为包装类之一(整数、Long等)称为“自动装箱”,并且就像名称所说的那样,是自动执行的。

为什么允许这样做?因为它对用户来说非常方便。除了自动拆箱,它还允许您非常接近地将包装类视为它们包含的原始值。

一些术语:你只“调用”方法,而不是变量或字段“呼叫”表示“将控制权转移到”。

在像整数这样的类中,你甚至不知道它有什么字段。你只知道它可以在一定范围内存储整数值。值只能通过调用构造函数或返回整数的静态方法之一输入到整数中。

Integer 的文档,以防您还没有看到它。请注意,没有“更改”整数值的操作;我们说它是“不可变的”。如果你想要一个不同的值,你只能创建一个新的整数。

杨良平
2023-03-14

仅当在类或方法中调用了字段时,才能将值存储在对象中。

这种说法毫无意义。我分不清这是错是对,只是……没有道理。

如果不实例化一个对象,它就不能调用它的值字段,因为值不是静态的。我只是不明白这怎么可能。

Javac看到后说:嘿,你把一个正方形的peg(int类型的常量)塞进一个圆孔(对象类型变量)-这没有意义。除了在Java语言规范中明确指出的,如果int表达式出现在int表达式不应该出现的地方,但是整数表达式可以正常工作,那么“应用自动装箱”。

“应用自动装箱”的意思是:假设程序员打算写:< code>Integer.valueOf(表达式)而不是他们所写的内容。

因此:

Integer x = 56;
Integer x = Integer.valueOf(56);

是一样的。它们是如此的相同,以至于产生了相同的字节码。无论如何编写,对valueOf的调用都在类文件中。让我们测试一下:

> cat Test.java
class Test {
    Integer x = 56;
}

> javac Test.java
 (`javap` is part of java distributions and prints bytecode)
> javap -private -c Test
Compiled from "Test.java"
class Test {
  java.lang.Integer x;

  Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: bipush        56
       7: invokestatic  #7                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      10: putfield      #13                 // Field x:Ljava/lang/Integer;
      13: return
}

看看这个——调用静态方法< code>Integer.valueOf,尽管< code>Integer.valueOf在我们的Test.java文件中根本没有出现。

那么,Integer是如何实现的呢。工作价值?

本质上,它的工作原理如下:

package java.lang;

public class Integer {
    private static final Integer[] CACHE = generateCache();

    private final int value;
    public Integer(int value) {
        this.value = value;
    }

    private static Integer[] generateCache() {
        for (int i = 0; i < 256; i++) {
            CACHE[i - 128] = new Integer(i);
         }
    }

    public static Integer valueOf(int v) {
        if (v >= -128 && v < 128) return CACHE[i + 128];
        return new Integer(v);
    }
}

换言之,Integer类预先创建了256个整数对象,从-128到127(为什么会有这些值?呃,因为sun认为这些值会经常出现,25年前缓存它们是值得的)。如果valueOf()的值介于-128和127之间,则会得到其中一个缓存。如果你在它之外赋值of,你会得到一个新的对象。

我们也可以证明:

> cat Example.java
class Example {
    public static void main(String[] args) {
        Integer a = -100;
        Integer b = -100;
        Integer c = 200;
        Integer d = 200;
        System.out.println("a == b? " + (a == b));
        System.out.println("c == d? " + (c == d));
        System.out.println("ident-hash a: " + System.identityHashCode(a));
        System.out.println("ident-hash b: " + System.identityHashCode(b));
        System.out.println("ident-hash c: " + System.identityHashCode(c));
        System.out.println("ident-hash d: " + System.identityHashCode(d));
    }
}
> java Example.java
a == b? true
c == d? false
ident-hash a: 1880794513
ident-hash b: 1880794513
ident-hash c: 1991313236
ident-hash d: 736778932

这段代码显示了-100的整数。valueOf调用返回的是完全相同的对象(==比较引用标识,即:它是同一个对象吗?当用于对象时,它不会比较值。a和b只是指向同一对象,而c和d指向具有相同值的不同对象)。

这就像在郊区某个地方建造的一堆相同的房子: a和b就像写着相同地址的纸片,而c和d就像写着不同地址的纸片,但是这些地址的两栋房子看起来是一样的。

 类似资料:
  • 我正在使用redux saga。执行分派时,会执行likePost和addPost等函数。 然后每次我使用异步存储。获取令牌的getItem。换句话说,它是重叠的 因为我必须使用jwt令牌 我需要不断传递这样的头到api。这也是重叠 这个怎么用没有冗余,或者说怎么用最方便? 这是我的密码 (saga/post.js) (佐贺/index.js)

  • 这是我第二次使用它,也是我第一次得到非常好的帮助,所以我希望我能得到更多的帮助! 背景: 我的程序通过创建一个保存余额和其他东西的对象来测试我的 类。说明说我需要覆盖子类的“提款”和“存款”方法以跟踪交易。 我这样做了,但它不使用当前余额,而是只发送一个0。我希望能够保留新的余额,以便它实际从当前余额中提取或存款。 抱歉,如果这毫无意义,如果需要任何澄清,我将尝试以不同的方式解释。 以下是我的代码

  • 我试图在不使用导入语句的情况下从Arrays类调用这个方法:你能告诉我怎么了吗? 非常感谢

  • 我有一个Spring Boot应用程序,注释为。几乎所有的存储库都需要实现一些自定义逻辑,这是使用完成的。 是否有方法创建将从机制中排除的存储库?

  • 问题内容: 我正在开发一个文档测试框架-基本上是PDF的单元测试。测试是框架定义的类的实例的(修饰)方法,并且在运行时定位并实例化这些实例,并调用这些方法以执行测试。 我的目标是减少将要编写测试的人员所关心的古怪的Python语法,因为这些人可能是也可能不是Python程序员,甚至根本不是很多程序员。因此,我希望他们能够为方法编写“ def foo():”而不是“ def foo(self):”,