类与 Object 面试题
1. 以下程序执行的结果是?
class ExecTest {
public static void main(String[] args) {
Son son = new Son();
}
}
class Parent{
{
System.out.print("1");
}
static{
System.out.print("2");
}
public Parent(){
System.out.print("3");
}
}
class Son extends Parent{
{
System.out.print("4");
}
static{
System.out.print("5");
}
public Son(){
System.out.print("6");
}
}
答:打印的结果是:251346
加载顺序如下:
执行父类的静态成员;
执行子类的静态成员;
父类的实例成员和实例初始化;
执行父类构造方法;
子类的实例成员和实例初始化;
子类构造方法。
Java的实例化顺序
1、牢记:静态和非静态分开处理
(1)使用到静态加载时,静态又分为: 静态变量, 静态代码块,其中加载顺序是按照类中书写的先后顺序加载的
(2)非静态加载顺序: 按照非静态书写顺序加载 /()执行
(3)静态方法,实例方法只有在调用的时候才会去执行
(4)当静态加载中遇到需要加载非静态的情况: 先加载非静态再加载静态(因为非静态可以访问静态,而静态不能访问非静态)
public static Text t1 = new Text("t1");
// 当加载静态变量是需要先加载构造器, 那就转为先加载所有非静态属性
2、静态变量声明 一定 放在使用前面
3、main是否第一句先执行
Java程序运行时,第一件事情就是试图访问main方法,因为main相等于程序的入口,如果没有main方法,程序将无法启动,main方法更是占一个独立的线程,找到main方法后,是不是就会执行mian方法块里的第一句话呢?
答:不是
因为main方法虽然是一个特殊的静态方法,但是还是静态方法,此时JVM会加载main方法所在的类,试图找到类中其他静态部分,即首先会找main方法所在的类。
4、父类、子类加载顺序
5、总结
1、父类的静态变量和静态块赋值(按照声明顺序)
2、自身的静态变量和静态块赋值(按照声明顺序)
3、main方法
3、父类的成员变量和块赋值(按照声明顺序)
4、父类构造器赋值
5、自身成员变量和块赋值(按照声明顺序)
6、自身构造器赋值
7、静态方法,实例方法只有在调用的时候才会去执行
2. 以下程序执行的结果是?
class A {
public int x = 0;
public static int y = 0;
public void m() {
System.out.print("A");
}
}
class B extends A {
public int x = 1;
public static int y = 2;
public void m() {
System.out.print("B");
}
public static void main(String[] args) {
A myClass = new B();
System.out.print(myClass.x);
System.out.print(myClass.y);
myClass.m();
}
}
答:打印的结果是:00B
题目解析:在 Java 语言中,变量不能被重写。
变量不能被重写(覆盖),”重写“的概念只针对方法,如 变量不能被重写(覆盖),”重写“的概念只针对方法, ), 果在子类中”重写“了父类中的变量,那么在编译时会报错。 果在子类中”重写“了父类中的变量,那么在编译时会报错。
System.out.print(myClass.x); public int x = 0;
System.out.print(myClass.y); public static int y = 0;
myClass.m(); public void m() {
System.out.print("B");
}
考察多态。子类以父类的方式出现,子类在工作时以自己的方式实现,子类特有的属性和方法不得使用。
3. 以下程序执行的结果是?
class A {
public void m(A a) {
System.out.println("AA");
}
public void m(D d) {
System.out.println("AD");
}
}
class B extends A {
@Override
public void m(A a) {
System.out.println("BA");
}
public void m(B b) {
System.out.println("BD");
}
public static void main(String[] args) {
A a = new B();
B b = new B();
C c = new C();
D d = new D();
a.m(a);
a.m(b);
a.m(c);
a.m(d);
}
}
class C extends B{}
class D extends B{}
答:打印结果如下。
BA
BA
BA
AD
题目解析:
第一个 BA:因为 A 的 m() 方法,被子类 B 重写了,所以输出是:BA;
第二个 BA:因为 B 是 A 的子类,当调用父类 m() 方法时,发现 m() 方法被 B 类重写了,所以会调用 B 中的 m() 方法,输出就是:BA;
第三个 BA:因为 C 是 B 的子类,会直接调用 B 的 m() 方法,所以输出就是:BA;
第四个 AD:因为 D 是 A 的子类,所以会调用 A 的 m() 方法,所以输出就是:AD。
一,父类引用指向子类的对象时,如果方法没有被子类重写,调用的是父类的方法和变量,如果方法被重写,调用的是子类的方法。 二,对于一的特殊情况,如果一个方法的参数列表没有找到,会把向上强制转型,继续查找。 以a.m©为例。 a.m()方法被子类重写了,所以会在B类中找,但是参数列表中没有C类,会把c向上转换,就是B类,对于A类,m方法中还是没有B类,就会继续向上转成A类,这个时候A类m方法有A类型参数,但是该方法又被子类重写了,所以调用B类中的m(a)方法。 所以输出的是BA
public void m(B b) { //是子类独有的方法,不能调用
System.out.println("BD");
}
考察多态。子类以父类的方式出现,子类在工作时以自己的方式实现,子类特有的属性和方法不得使用。