笔试题目一:问如下代码会输出什么?
public class PoliTest {
public static void main(String[] args) {
Parent p = new Child();
p.doSomething();
}
}
class Parent {
public void doSomething() {
System.out.println("parent");
}
}
class Child extends Parent {
@Override
public void doSomething() {
System.out.println("child");
}
}
答案:控制台会输出child。这是一个多态的问题。虽然引用类型是父类,但是因为真正所指向的是子类的对象所以调用的是子类的方法。
关于多态:父类或者接口的引用指向子类或者实现接口的类的对象
笔试题目二:问如下代码编译能否通过?并说明为什么?
public class PoliTest {
public static void main(String[] args) {
Parent p = new Child();
p.doSomething2();
}
}
class Parent {
public void doSomething() {
System.out.println("parent");
}
}
class Child extends Parent {
@Override
public void doSomething() {
System.out.println("child");
}
public void doSomething2() {
System.out.println("child another method");
}
}
答案:编译通不过。因为虽然Parent p = new Child();是多态,但是使用的还是Parent类型的引用了,Parent中根本没有doSomething2()的方法所以在编译阶段就通不过。也就是说多态的情况下父类或者接口的引用所调用的方法只能是父类与子类共同拥有的方法或者接口与实现类共同拥有的方法。 如果在代码Parent p = new Child();语句下插入语句Child child = (Child) p; child.doSomething2();则可以让编译通过并在控制台打印出child another method。也就是说如果是子类自己的方法,但是当前的引用是父类的引用时,需要进行向下类型转换才可以调用属于子类自己的方法。
笔试题目三:问多态是运行时的行为还是编译时的行为?(理解这点很重要)
答案:多态是运行时的行为。我们用下面程序来进一步说明该问题,代码如下:
import java.util.*;
public class PoliTest {
public Parent generate() {
Random rand = new Random();
int v = rand.nextInt(3);
switch(v) {
case 0:
return new Child1();
case 1:
return new Child2();
case 2:
return new Child3();
}
return null;
}
public static void main(String[] args) {
PoliTest p = new PoliTest();
Parent parent = p.generate();
parent.doSomething();
}
}
class Parent {
public void doSomething() {
System.out.println("parent");
}
}
class Child1 extends Parent {
@Override
public void doSomething() {
System.out.println("child-1");
}
}
class Child2 extends Parent {
@Override
public void doSomething() {
System.out.println("child-2");
}
}
class Child3 extends Parent {
@Override
public void doSomething() {
System.out.println("child-3");
}
}
generate方法是通过生成的随机数最终来决定生成哪个Parent子类的对象,随机数我们都知道发生在运行期的,编译的时候根本无法知晓,换言之具体生成哪个对象并返回也是在运行期才确定的。所以说多态是运行时的行为。
笔试题目四:java中是通过方法覆写与方法重载来实现多态的么?
答案:不是。在子类继承了父类的情况下才会出现方法覆写的场景,即方法覆写与子类和父类两个因素有关,而方法重载在一个类中就可以完成不牵扯到其他类。
Thinking in java
People are often confused by other,non-object-oriented features of java,like method overloading,which are sometimes presented as object-oriented.Don't be fooled:If it isn't late binding, it isn't ploymorphism.
方法覆写涉及到多态,而方法重载与多态无关。
笔试题目五:如下代码返回结果是什么?并说明相应的理由。
public class ArrayTest {
public static void main(String[] args) {
char[] ch1 = new char[2];
ch1[0] = 'a';
ch1[1] = 'b';
char[] ch2 = new char[2];
ch2[0] = 'a';
ch2[1] = 'b';
System.out.println(ch1.equals(ch2));
//System.out.println(new String(ch1).equals(new String(ch2)));
//System.out.println(Arrays.equals(ch1, ch2));
}
}
答案:返回的是false,数组是一个对象所以它必然继承Object类,而数组又是特殊的对象,不像String对象有专门的类String,让我们可以去查看是否覆写了equals方法,不过通过该程序运行结果我们可以知道它只是继承了Object的equals方法而已并没有进行覆盖。如果想对两个char数组的内容进行比较可以使用字符串以及Arrays.equals(char[] ch, char[] ch2)的方法,如上述代码注释部分。
笔试题目六:请用两种方式写出单例模式
代码如下:
public class Singleton {
private static Singleton singleton = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return singleton;
}
}
public class Singleton {
private static Singleton singleton;
private Singleton() {
}
public static Singleton getInstance() {
if (null == singleton) {
singleton = new Singleton();
}
return singleton;
}
}