2020-12-30 面试题
1.最有效率的方法计算2*8?
答:2<<3(左以相当于乘以2的3次方,右移相当于除以2的3次方)
补充:
我们为编写的类重写hashCode方法时,可能会看到如下所示的代码,
为什么要使用这样的乘法运算来产生哈希码(散列码),
而且为什么这个数是个素数,
为什么通常选择31这个数?
选择31是因为可以用移位和减法运算来代替乘法,从而得到更好的性能。说到这里你可能已经想到了:31 * num 等价于(num << 5) - num,左移5位相当于乘以2的5次方再减去自身就相当于乘以31,现在的VM都能自动完成这个优化。
public class PhoneNumber {
private int areaCode;
private String prefix;
private String lineNumber;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + areaCode;
result = prime * result
+ ((lineNumber == null) ? 0 : lineNumber.hashCode());
result = prime * result + ((prefix == null) ? 0 : prefix.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PhoneNumber other = (PhoneNumber) obj;
if (areaCode != other.areaCode)
return false;
if (lineNumber == null) {
if (other.lineNumber != null)
return false;
} else if (!lineNumber.equals(other.lineNumber))
return false;
if (prefix == null) {
if (other.prefix != null)
return false;
} else if (!prefix.equals(other.prefix))
return false;
return true;
}
}
2. 数组为甚没有length()方法?String有没有length()方法?
答:数组没有length()方法,有length属性。
String有length()方法。
JavaScript中,获得字符串的长度,时通过lengrh属性得到的。
3. 在Java中,如何跳出当前的多重嵌套循环?
答:在最外层循环前加如一个标记A,然后用break A;可以跳出多重循环。
ok:
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
system.out.println("i="+i+",j="+j);
if(j==5)break ok;
}
}
4. 构造器 constructor 是否可以被重写 override?
答:构造器不能被继承,因此不能被重写,但可以被重载。
5. 两个对象值相同(x.equals(y)==true),但却可以有不同的hashcode,这句话对不对?
答:不对,如果对象满足x.equals(y)==true 他们的哈希码应当相容。
Java中equals方法和hashcode方法时这样规定的:
1.如果两个对象相同,equals方法返回true,那么他们的hashCode值一定相同。
2.如果两个对象的hashCode相同,他们不一定相同。
6.是都可以继承String类?
答:不可以。String类是final类,不可以被继承。
7.当一个对象被当作参数传递到一个方法后,此方法可以改变这个对象的属性,并返回变化后的结果,那么这里到底是值传递还是引用传递?
答:值传递。Java语言中方法调用只支持参数的值传递。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的属性可以在被调用的过程中被改变。但对对象引用的改变时不会影响到调用者的。
class Program {
public static void swap(ref int x, ref int y) {
int temp = x;
x = y;
y = temp;
}
public static void Main (string[] args) {
int a = 5, b = 10;
swap (ref a, ref b);
// a = 10, b = 5;
Console.WriteLine ("a = {0}, b = {1}", a, b);
}
}
8.String和StringBuilder、StringBuffer 区别?
答:Java平台提供两种类型的字符串:String 和StringBuffer/StringBuilder ,他们可以储存和操作字符串。其中String是只读字符串,也就意味者String引用的字符串内容是不能被改变的。而StringBuffer/StringBuilder类表示的字符串对象可以直接进行修改。StringBuilder是Java5中引入的。它和StringBuffer 的方法完全相同。区别在于他是在单线程环境下使用的,因为它的所有方面都没有被synchronized修饰,因此他的效率比StringBuffer高。
9.重载Overload 和重写Override的区别。重载的方法能否根据返回类型进行区分?
答:放法的重载和重写都是实现多态的方式,
区别在于前者实现的是编译时的多态性,而后者实现的时运行时的多态性。
重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)视为重载;
重写发生在子类于父类之间,重写要求子类被重写的方法于父类被重写的方法有相同的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常。
重载对返回类型没有特殊的要求。
*10.描述一下JVM加载class文件的原理机制?
答: JVM中类的装载是由类加载器 ClassLoader 和它的子类来实现的。Java中的类加载器是一个重要的Java运行时系统组件,它负责在运行时查找和装入类文件中的类。
由于Java的跨平台性,经过编译的Java源程序并不是一个可执行程序,而是一个或多个类文件,当Java 程序需要使用某个类时,JVM会确保这个类已经被加载、链接(验证、准备和解析)和初始化。类的加载是指把类的.class文件中的数据读入到内存中,通常创建一个字节数组读入.class文件,然后产生于所加载类相对应的Class对象。加载完成后,Class对象还不完整,所以此时的类还不可用。当类被加载后九进入链接阶段,这一阶段包括验证、准备和解析三个步骤。最后JVM进行初始化。
从Java 2(JDK 1.2)开始,类加载过程采取了父亲委托机制(PDM)。PDM更好的保证了Java平台的安全性,在该机制中,JVM自带的Bootstrap是根加载器,其他的加载器都有且仅有一个父类加载器。类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加载。JVM不会向Java程序提供对Bootstrap的引用。下面是关于几个类加载器的说明:
Bootstrap:一般用本地代码实现,负责加载JVM基础核心类库(rt.jar);
Extension:从java.ext.dirs系统属性所指定的目录中加载类库,它的父加载器是Bootstrap;
System:又叫应用类加载器,其父类是Extension。它是应用最广泛的类加载器。它从环境变量classpath或者系统属性java.class.path所指定的目录中记载类,是用户自定义加载器的默认父加载器。