JAVA 一个有趣的现象 你能猜到如下代码运行的结果吗?

本文深入解析了Java中Short类型数据比较的两种方法及自动装箱池原理,详细解释了为何在不同范围内使用==和equals方法得到不同结果,并通过代码实例展示了Short类型数据比较的正确方式。

请看如下代码:

1、大家猜猜看打印结果是什么?

public class Test {

public static void main(String[] args) {

Short a = 1;
Short b = 1;
System.out.println(a == b);
System.out.println(a.equals(b));
}

}

2、如下代码大家猜猜看结果

public class Test {

public static void main(String[] args) {

Short e = 128;
Short f = 128;
System.out.println(e == f);
System.out.println(e.equals(f));
}
}

3、如下代码大家猜猜看结果public class Test {

public static void main(String[] args) {

Short a = 1;
Short b = 1;
Short c = 127;
Short d = 127;
Short e = 128;
Short f = 128;
Short g = 129;
Short h = 129;
System.out.println(a == b);
System.out.println(a.equals(b));
System.out.println(c == d);
System.out.println(c.equals(d));
System.out.println(e == f);
System.out.println(e.equals(f));
System.out.println(g == h);
System.out.println(g.equals(h));
}
}


以上代码结果如下

第一个代码:

 true 

true

第二个代码:

false

true

第三个代码:

true
true
true
true
false
true
false
true


很奇怪吧,当Short类型的数据,如果小于等于127的时候使用==和使用equal方法会得到相同的结果。I

 当大于等于128的时候,使用==和使用equal方法得到的结果会相反。

所以比较Short类型的数据要使用equal方法才是正确的。

默认情况下Integer也是相同的结果。

所以不管Double Float Long Integer Short....都使用equal方法比较。


应该是java自动装箱时候的池问题。类似于String池。后来看了一下代码果然是这样。

下面是Short包装类的缓存池。

    private static class ShortCache {
private ShortCache(){}


static final Short cache[] = new Short[-(-128) + 127 + 1];


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


刚才为什么说默认情况下Integer也是相同的结果呢?

下面 请看Intege类的代码:

  private static class IntegerCache {
        static final int high;
        static final Integer cache[];


        static {
            final int low = -128;


            // high value may be configured by property
            int h = 127;
            if (integerCacheHighPropValue != null) {
                // Use Long.decode here to avoid invoking methods that
                // require Integer's autoboxing cache to be initialized
                int i = Long.decode(integerCacheHighPropValue).intValue();
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - -low);
            }
            high = h;


            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
        }


        private IntegerCache() {}
    }



  /**
     * Cache to support the object identity semantics of autoboxing for values between 
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage. During VM initialization the
     * getAndRemoveCacheProperties method may be used to get and remove any system
     * properites that configure the cache size. At this time, the size of the
     * cache may be controlled by the vm option -XX:AutoBoxCacheMax=<size>.
     */


    // value of java.lang.Integer.IntegerCache.high property (obtained during VM init)
    private static String integerCacheHighPropValue;


    static void getAndRemoveCacheProperties() {
        if (!sun.misc.VM.isBooted()) {
            Properties props = System.getProperties();
            integerCacheHighPropValue =
                (String)props.remove("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null)
                System.setProperties(props);  // remove from system props
        }
    }



可以看出Integer的自动装箱池是可配置的,怎么配置?根据注释中的提示,设置运行时候的vm arguments -xx:AutoBoxCacheMax=256

把 256换成你想要的值即可。


### Account.java 示例代码 以下是 `Account.java` 的一个典型实现示例,该类通常用于演示银行账户的操作逻辑,包括存款、取款和余额查询等功能。 ```java public class Account { private double balance; public Account(double initialBalance) { if (initialBalance > 0.0) { this.balance = initialBalance; } } public void deposit(double amount) { if (amount > 0.0) { balance += amount; System.out.println("存入金额:" + amount); } else { System.out.println("存款失败:请输入有效的正数!"); } } public boolean withdraw(double amount) { if (balance >= amount && amount > 0.0) { balance -= amount; System.out.println("取出金额:" + amount); return true; } else { System.out.println("取款失败:余额不足或输入无效!"); return false; } } public double getBalance() { return balance; } public static void main(String[] args) { // 创建一个新的账户对象并初始化余额为100元 Account account = new Account(100); // 存款操作 account.deposit(50); // 取款操作 account.withdraw(30); // 查询当前余额 System.out.println("当前余额:" + account.getBalance()); } } ``` #### 运行结果说明 当执行上述代码时,控制台会显示如下输出: ``` 存入金额:50.0 取出金额:30.0 当前余额:120.0 ``` 此运行结果显示了初始余额为100元的情况下,经过一次存款(50元)和一次取款(30元),最终余额变为120元的结果[^1]。 --- ### 多线程环境下的扩展示例 如果希望进一步探讨多线程环境下对共享资源的安全访问,则可以通过引入同步机制来保护账户数据的一致性和完整性。以下是一个简单的基于线程安全的改进版本: ```java public class AccountWithThreadSafety { private double balance; public synchronized void deposit(double amount) { if (amount > 0.0) { balance += amount; System.out.println(Thread.currentThread().getName() + ": 存入金额:" + amount); } else { System.out.println(Thread.currentThread().getName() + ": 存款失败:请输入有效的正数!"); } } public synchronized boolean withdraw(double amount) { if (balance >= amount && amount > 0.0) { balance -= amount; System.out.println(Thread.currentThread().getName() + ": 取出金额:" + amount); return true; } else { System.out.println(Thread.currentThread().getName() + ": 取款失败:余额不足或输入无效!"); return false; } } public synchronized double getBalance() { return balance; } public static void main(String[] args) throws InterruptedException { final AccountWithThreadSafety account = new AccountWithThreadSafety(); Thread t1 = new Thread(() -> { for (int i = 0; i < 5; i++) { try { Thread.sleep(100); account.deposit(10); } catch (InterruptedException e) { e.printStackTrace(); } } }, "T1"); Thread t2 = new Thread(() -> { for (int i = 0; i < 5; i++) { try { Thread.sleep(150); account.withdraw(8); } catch (InterruptedException e) { e.printStackTrace(); } } }, "T2"); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("最终余额:" + account.getBalance()); } } ``` 在此场景下,两个线程分别模拟多次存款和取款行为,并通过`synchronized`关键字确保每次操作都互斥完成,从而避免竞争条件引发的数据不一致问题[^2]。 --- ### 死锁风险分析与规避建议 尽管上述例子展示了如何利用同步解决基本的竞争状态,但在更复杂的业务流程中仍需警惕潜在的死锁隐患。例如,若存在多个账户间的转账需求而未遵循统一加锁顺序,则可能触发死锁现象。因此推荐采用显式的锁升级策略或者借助高级并发工具如`ReentrantLock`配合超时机制降低此类风险[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值