关于包装类中的"等等"

1、equals方法与"=="的区别

         Java中可以使用关系操作符"=="或者特殊方法equals()来比较两个对象或变量的相等关系。返回的都是布尔值结果。但是这两个东西常常让人头昏脑胀的,先来看看两段代码:
Java代码
//代码一:比较整形包装类对象的"=="关系
Integer n1=new Integer(1); 
Integer n2=new Integer(1); 
System.out.println(n1==n2);// 打印结果:false
//代码二:比较整形变量的"=="关系
int n3=1;
int n4=1; 
System.out.println(n3==n4); //打印结果: true 

两段代码的打印结果完全不同,这主要是因为Java对象和Java基本数据类型所定义的变量在内存中所存储的方式是完全不一样的。  

       Java对象存储使用到了栈和堆(详细内容见 《Java五种不同的数据存储环境 》) 。其中,对象的引用(相当与C中的指针,保存了对象内容所在的地址)存储在栈中,而对象的具体内容却存储在堆中。运行的时候通过栈中的地址直接找到堆中对象存储的具体内容。 但基本数据类型所定义的变量直接携带“值”存储于栈中,这样做的用意在于提高运行效率。

        "=="比较的都是栈中的数据 , 也就是比较对象的引用和变量的值。 这一点很重要。
       代码一中的n1和n2是对象,他们在堆中不同的存储位置上创建了两个不同的对象(虽然对象的内容一样,但存储的地址不一样)。因此n1和n2在栈中记录的数据自然是两个对象在堆中的地址。当然比较起来不一样。
       代码二中的n3和n4并非对象,而是变量,变量在栈中的内容存储的是变量的值(堆中是没有变量的居住环境的)。因此比较栈中的内容当然是一样的,都是1。下面这个图已经说的很清楚了。

            栈                 堆                            栈
                |---------------|    |-------------|                 |---------------|
                |   n1: 0x1AD2 ---->    1     |                 |    n3:  1      |
                |---------------|    |------------- |                |---------------|

                |   n2: 0xB8DC ---->    1    |                 |    n4:  1      |
                |---------------|    |-------------|                 |---------------|
我们再看看equals行为:
//代码三:比较整形包装类的equals关系
Integer n1=new Integer(1);
Integer n2=new Integer(1);
System.out.println(n1.equals(n2));//打印结果:true 

//代码四:比较自定义类的equals关系
Value v1=new Value(1);
Value v2=new Value(1);
System.out.println(v1.equals(v2));//打印结果:false

先声明一点,变量是不存在方法行为。equals()方法只对对象有效。
     equals() 方法的默认行为 仍然是比较栈中的数据, 但要注意被子类覆盖的行为 。 但要注意:“默认行为 ”这几个字,换句话说:Java默认的equals()方法比较的仍然是对象引用,但OOP有一种重载特性,我们当然可以在自己的类中覆盖 equals()方法来改变这种行为。代码三中类Integer的equals()方法就覆盖了默认行为,这个方法比较的是对象的内容(具体实现可以看 JDK 1.5的源代码包)。代码四是自己编的一个类,没有重载equals()方法,这样v1.equals其实调用的是v1自动向上转型成万类之始的 Object类中的equals()方法,这就是我们所说的"默认行为"了。

2、String类型的常量池造成的相等问题。

  问题还是没有结束,下面两段代码更匪夷所思: 
Java代码
//代码五: 字符串的"=="和equals关系
String s1=new String("aaaa");
String s2=new String("aaaa");
System.out.println(s1==s2);//打印结果:false 
System.out.println(s1.equals(s2))//打印结果:true

//代码六:字符串的"=="和equals关系
String s3="aaaa";
String s4="aaaa";

System.out.println(s3==s4);//打印结果:true
System.out.println(s3.equals(s4))//打印结果:true  

String类型是并非基本数据类型,但它具有常量池这种特殊的存储结构。

  很显然,代码五中的s1和s2是对象引用,结果自然我们能理解了。但代码六中s3,s4的形式貌似基本数据类型的变量。但为什么具有 equals()方法行为呢?显然,s3,s4也不是基本数据类型,那"=="应该比较的是引用呀,怎么也true了呢?原来Java对String类型有一种特殊的关照,他会直接开辟一个String常量池,JVM会在String常量池中查找是否有"aaaa"这个字符串,有就返回,无就创建。当运行 String s3="aaaa";时,JVM会自动在String常量池中开辟一个空间用来存放“aaaa”,假设空间地址是0x5BC2。当运行到String s4="aaaa";JVM不会创建一个新的"aaaa",而是在String常量池中查找原有的"aaaa",再返回地址0x5BC2。因此s3,s4 仍然是引用,"=="比较的仍然是地址。但由于常量池的存在,这种存储方式使得相同字符串的地址是一样的(也就是说相同字符串只能有一个地址)。所以给我们很容易误解String的"=="比较的是内容了,其实不是的。

3、Integer类型的自动打包(autoboxing)功能造成的相等问题

     还有一种比较特殊的情况,请看下面两端代码:
Java代码
//代码七
Integer a=127;
Integer b=127;
System.out.println(a==b); //结果:true

//代码八
Integer c=128;
Integer d=128;
System.out.println(c==d); //结果:false

这里先阐述一下Integer a=127这样的语法形式。Integer是整形包装器类,127是int常量。编译器会调用Integer.valueOf(int)方法将int型常量自动打包(autoboxing)成包装器类。

      然后我们看看Integer.valueOf(int)的源代码:
Java代码
    /**
     * Returns a <tt>Integer</tt> instance representing the specified
     * <tt>int</tt> value.
     * If a new <tt>Integer</tt> instance is not required, this method
     * should generally be used in preference to the constructor
     * {@link #Integer(int)}, as this method is likely to yield
     * significantly better space and time performance by caching
     * frequently requested values.
     *
     * @param  i an <code>int</code> value.
     * @return a <tt>Integer</tt> instance representing <tt>i</tt>.
     * @since  1.5
     */
    public static Integer valueOf(int i) {
        final int offset = 128;
       if (i >= -128 && i <= 127) { // must cache 
            return IntegerCache.cache[i + offset];
        }
        return new Integer(i);
    }


    private static class IntegerCache {
        private IntegerCache(){}
        static final Integer cache[]= new Integer[-(-128) + 127 + 1];

        static {
            for(int i = 0; i < cache.length; i++)
                cache[i] = new Integer(i - 128);
        }
    }

看看Integer的源代码就知道了,其实Interger把-128—127之间的每一个值都建立了一个对应的Integer对象,并将这些对象组织成cache数组,类似一个缓存。 这个缓存数组中的Integer对象是可以安全复用的。也就是Integer a=127;和Integer b=127;中的引用a,b都是缓存数组中new Integer(127)对象的地址。所以代码七中的a==b自然是true

但要注意了,缓存数组只存储-128—127之间的Integer对象。对于其他的值的整形包装器,比如代码八中的Integer c,d=128分别在堆中创建了一个Integer对象用来存储128。两个引用的地址都不一样。

这里提一点:如果是Integer a=new Integer(127);这种常规形式创建的Integer是没有cache数组的。只有Integer a=127或Integer a=Integer.valueOf(127)这样的方式才能使用上cache数组。而且包装器的整形值在-128—127之间。

考虑柔性负荷的综合能源系统低碳经济优化调度【考虑碳交易机制】(Matlab代码实现)内容概要:本文围绕“考虑柔性负荷的综合能源系统低碳经济优化调度”展开,重点研究在碳交易机制下如何实现综合能源系统的低碳化与经济性协同优化。通过构建包含风电、光伏、储能、柔性负荷等多种能源形式的系统模型,结合碳交易成本与能源调度成本,提出优化调度策略,以降低碳排放并提升系统运行经济性。文中采用Matlab进行仿真代码实现,验证了所提模型在平衡能源供需、平抑可再生能源波动、引导柔性负荷参与调度等方面的有效性,为低碳能源系统的设计与运行提供了技术支撑。; 适合人群:具备一定电力系统、能源系统背景,熟悉Matlab编程,从事能源优化、低碳调度、综合能源系统等相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①研究碳交易机制对综合能源系统调度决策的影响;②实现柔性负荷在削峰填谷、促进可再生能源消纳中的作用;③掌握基于Matlab的能源系统建模与优化求解方法;④为实际综合能源项目提供低碳经济调度方案参考。; 阅读建议:建议读者结合Matlab代码深入理解模型构建与求解过程,重点关注目标函数设计、约束条件设置及碳交易成本的量化方式,可进一步扩展至多能互补、需求响应等场景进行二次开发与仿真验证。
<think>嗯,用户问的是Java的包装,我得先回顾一下相关知识。首先,包装是什么?应该是将基本数据型转换成对象的那种吧,比如Integer对应int,Double对应double。那Java有八种基本型,每种都有对应的包装,比如Integer、Character、Boolean这些。 接下来,用户可能需要了解为什么需要包装。我记得主要是为了在需要对象的时候使用,比如集合ArrayList只能存储对象,不能存基本型,这时候就需要包装。还有自动装箱和拆箱的功能,这应该是在Java 5引入的,方便开发者在基本型和包装之间自动转换。 然后,包装的主要用途可能有几点:作为对象使用、提供实用方法(比如转换方法parseInt)、支持泛型等等。可能还需要提到缓存机制,比如Integer的缓存范围是-128到127,这个在比较对象的时候需要注意,可能会用==产生错误的结果,应该用equals方法。 另外,包装的构造方法可能已经被标记为过时,推荐使用valueOf方法,因为这样可以利用缓存提高性能。还有自动装箱和拆箱的示例,比如Integer i = 10; 实际上是调用了Integer.valueOf(10),而拆箱的时候int j = i; 就是i.intValue()。 可能还需要注意一些常见的问题,比如空指针异常,当自动拆箱一个null的包装对象时会抛出NPE。还有性能问题,频繁的装箱拆箱可能影响性能,特别是在循环中需要注意。 总结一下,回答的结构应该是先介绍包装的概念,然后列举八种基本型对应的包装,接着讲用途,自动装箱拆箱,缓存机制,注意事项,最后给出示例代码。用户可能还会想知道为什么需要包装,或者使用时的常见错误,所以相关问题可以围绕这些点展开。</think><< Java的包装(Wrapper Classes)是为8种基本数据型提供的对象表示形式,主要作用是将基本型封装为对象,使其能用于面向对象场景。以下是核心要点: 一、8种包装对应关系 1. byte → java.lang.Byte 2. short → java.lang.Short 3. int → java.lang.Integer 4. long → java.lang.Long 5. float → java.lang.Float 6. double → java.lang.Double 7. char → java.lang.Character 8. boolean → java.lang.Boolean 二、主要用途 1. 对象化存储:用于需要对象参数的场景(如集合) 2. 型转换:提供parseXxx()和valueOf()等转换方法 3. 数处理:包含最大/最小等常量(如Integer.MAX_VALUE) 4. 支持泛型:泛型型参数必须是对象型 5. 空处理:可以表示null状态 三、自动装箱/拆箱(Autoboxing/Unboxing) ```java // 自动装箱(基本型 → 包装) Integer num = 10; // 实际执行 Integer.valueOf(10) // 自动拆箱(包装 → 基本型) int value = num; // 实际执行 num.intValue() ``` 四、缓存机制(以Integer为例) ```java Integer a = 127; // 使用缓存对象 Integer b = 127; // 使用缓存对象 System.out.println(a == b); // true Integer c = 128; // 新建对象 Integer d = 128; // 新建对象 System.out.println(c == d); // false ``` 缓存范围: - Integer:-128 ~ 127(可通过JVM参数调整) - Boolean:TRUE/FALSE静态实例 - Character:0 ~ 127 五、注意事项 1. 比较应使用equals()而非== 2. 自动拆箱可能导致NullPointerException 3. 性能敏感场景避免频繁装箱/拆箱 示例代码(型转换): ```java // String转int String str = "123"; int num = Integer.parseInt(str); // int转String int value = 456; String s = Integer.toString(value); ``` >>
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值