这根本不是多余的.使用变量有两个步骤:
>声明:此步骤告诉VM什么是变量的静态足迹.例如:对象a;将只有在Object类中声明的脚印可见,而Integer b;将在Integer类和所有继承的父类中声明所有足迹,直到Object可见.这是针对静态部分的.
> instanciation:此步骤告诉VM什么是变量的动态足迹.例如:List< String> c = new LinkedList< String>();,然后是c.put(“foo”);将使用LinkedList的put()方法实现,即使可见的是List :: put().有时,您将需要这种声明/实例,但需要覆盖以访问静态足迹不可见的非常具体的方法.例如,让我们考虑一个声明为public void method1(Object obj)的方法,并且您知道obj实例实际上是一个Integer,因此您将通过将对象转换为它来专门使用动态脚印:int value =((Integer) OBJ).intValue();
现在,至于字符串a =“A”;部分.为简单起见,Java已经简化了“原始”类的写法.更具体地说,从Java 1.5开始,您可以:
Integer n1 = 1;
Integer n2 = new Integer(1); // same thing
int n3 = n2;
一切正常.但有什么区别?考虑这段代码:
String a = new String("A");
String b = new String("A");
String c = "A";
String d = "A";
System.out.println("a:" + a.hashCode() + " = b:" + b.hashCode() + " == " + (a == b));
System.out.println("b:" + b.hashCode() + " = c:" + c.hashCode() + " == " + (b == c));
System.out.println("c:" + c.hashCode() + " = d:" + d.hashCode() + " == " + (c == d));
将输出
a:65 = b:65 == false
b:65 = c:65 == false
c:65 = d:65 == true
为什么?因为JVM正在尝试尽可能多地重用内存,并且由于a和b正在创建String的新实例,因此它们不共享相同的内存空间.但是,c和d使用常量字符串值(这是编译器优化),因此指向完全相同的String对象.