6、Java
有没有 goto
?
goto
是 Java 中的保留字,在目前版本的 Java 中没有使用。(根据 James Gosling (java 之父) 编写的 《The Java Programming Language》 一书的附录中给出了一个 Java 关键字列表,其中有 goto
和 const
,但是这两个是目前无法使用的关键字,因此有些地方将其称之为保留字,其实保留字这个词应该有更广泛的意义,因为熟悉C语言的程序员都知道,在系统类库中使用过的有特殊意义的单词或者词组都被视为保留字)
7、 int 和 Integer 有什么区别?
Java 是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入了基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java 为每个基本数据类型都引入了对应的包装类型(wrapper class), int 的包装类就是Integer, 从 Java 5
开始引入了自动装箱/拆箱机制,使得二者可以相互转换。
Java 为每个原始类型提供了包装类型:
原始类型 | 包装类型 |
---|---|
byte | Byte |
short | Short |
char | Character |
int | Integer |
float | Float |
double | Double |
long | Long |
@Test
public void test04(){
int a1 = 12;
int a2 = 12;
Integer b1 = new Integer(12);
Integer b2 = new Integer(12);
Integer b3 = new Integer(127);
Integer c1 = 127;
Integer c2 = Integer.valueOf(127);
Integer d1 = 128;
Integer d2 = 128;
System.out.println(a1 == a2); //true int基本数据类型比较值
System.out.println(a1 == b1); //true a1、b1 int和Integer使用==比较 Integer会执行拆箱
System.out.println(b1 == b2); //false b1,b2 是引用类型,比较堆中的内存地址
System.out.println(b3 == c1); //false b3指向堆内存的引用,c1 指向常量池
System.out.println(c1 == c2); //true //因为-128到127java已经进行了缓存。 故相等
System.out.println(d1 == d2); //false d1、d2 引用类型 128没有缓存 使用new Integer
}
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
8、& 和 && 的区别?
-
& 运算符有两种用法:
-
按位与
-
逻辑与
-
-
&& 运算符是短路与运算
区别:
&& 短路与,如果左边的表达式的值是false,右边的表达式会被直接短路掉,不会进行运算。很多时候我们可能都需要用到&&而不是&。
例子:
username!=null && !username.equals("")
,二者顺序不能交换,更不能用 & 运算符,因为第一个条件如果不成立,则无法进行字符串的equals比较,否则会产生 NullPointerException
(空指针异常)。注意:逻辑或运算符(|) 和短路或运算符(||) 的差别也是如此。
9、解释内存中的栈(stack)、堆(heap)和方法区(method area) 的用法。
通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用 JVM 中的栈空间;而通过 new 关键字和构造器创建的对象则放在堆空间,堆是垃圾收集器管理的主要区域,由于现在的垃圾收集器都采用分代收集算法,所以堆空间还可以细分为新生代和老生代,再具体一点可以分为 Eden、Survivor(又可分为 From Survivor 和 To Survivor)、Tenured; 方法区和堆都是各个线程共享的内存区域,用于存储已经被 JVM 加载的类信息、常量、静态变量、JIT 编译器编译后的代码等数据;程序中的字面量(literal)如直接书写的100、“hello” 和常量都是放在常量池中,常量池是方法区的一部分。栈空间操作起来最快但是栈很小,通常大量的对象都是放在堆空间,栈和堆的大小都可以通过 JVM 的启动参数来进行调整,栈空间用光了会引发StackOverflowError
,而堆和常量池空间不足则会引发OutOfMemoryError
。
String str = new String("hello world");
上面的语句中变量 str 放在栈上,用 new 创建出来的字符串对象放在堆上,而 “hello world” 这个字面量则是放在方法区。
补充1:
较新版本的 Java (从 Java 6 的某个更新开始)中,由于 JIT 编译器的发展和”逃逸分析“技术的逐渐成熟,栈上分配、标量替换等优化技术使得对象一定分配在堆上这件事情已经变得不那么绝对了。
补充2:
运行时常量池相当于Class 文件常量池具有动态性,Java语言并不要求常量一定只有编译期间才能产生,运行期间也可以将新的常量放入池中,String 类 的 intern() 方法就是这样的。(String 的 intern() 方法:是一个本地方法,作用是:如果字符串常量池中已经包含了一个等于此String对象的字符串,则返回这个字符串对象在常量池中的引用;如果没有包含,会将此字符串先存入常量池,并然后返回此string的引用。(谁调用intern方法,谁就是那个String对象))
@Test
public void test05(){
String s1 = new StringBuilder("go").append("od").toString();
String s2 = new StringBuilder("ja").append("va").toString();
System.out.println(s1.intern() == s1); // true
System.out.println(s2.intern() == s2); // false 常量池中自带“java”吗?
}
10、Math.round(11.5)
等于多少?Math.round(-11.5)
等于多少?
Math.round(11.5)
的返回值是12, Math.round(-11.5)
的返回值是 -11。 四舍五入的原理是在参数上加0.5然后进行向下取整。
@Test
public void test06(){
System.out.println(Math.round(11.5)); // 12
System.out.println(Math.round(-11.5)); // -11
}