写给自己的Java面试题(2):复用类、多态
by 伊布
可以通过this访问static变量吗?
可以。static可以通过类和对象来访问,this是对象的引用,当然可以通过this访问static变量、方法。
类域初始化的规则?
本质上都是赋值为0,具体到基础类型则为0(int), 0.0(float), false(boolean),而对象引用则为null。 注意String, Integer这种基础类型的包装类,类域实际是个引用,print出来是null的。
父类和子类的初始化顺序是什么?
先父类,后子类,不管子类里有没有调用super(args);来初始化父类。父类的域的初始化 -> 父类构造函数 -> 子类域初始化 -> 子类构造函数
类域初始化早,还是构造函数早?
类域。比类域更早的是静态域和静态代码块。
完整的父类、子类初始化顺序?
1.父类静态成员和静态初始化块,按在代码中出现的顺序依次执行(只发生在类加载时)。 2.子类静态成员和静态初始化块,按在代码中出现的顺序依次执行(只发生在类加载时)。 3.父类实例成员和实例初始化块,按在代码中出现的顺序依次执行(以下为对象初始化)。 4.执行父类的构造方法。 5.子类实例成员和实例初始化块,按在代码中出现的顺序依次执行。 6.执行子类的构造方法。
特别的: 1、如果B extend A,但是只是调用了A的静态域,那么也只会初始化A类,B类当做没看见。btw,这就是个坑。 2、如果实例初始化块在实例成员之前,并且都赋值了实例成员,那么实例最终的值是实例成员定义时赋的值。可以这么理解,实例成员先声明,然后将初始化块和声明时的赋值,按顺序执行。
构造器是静态方法吗?
构造器不是“方法”,不是对象或者类的成员;构造器可以使用this,也不符合静态方法不能访问this的限制。 另外,构造器有其“静态”的特点,即静态绑定。 java虚拟机规范定义了4种不同种类的方法调用:
- invokeStatic,调用静态方法
- invokeSpecial,调用实例方法,局限于 super方法调用,private 方法调用、构造器调用
- invokeVitual,调用一般实例方法(包括声明为final但不是private的方法)
- invokeInterface,调用接口方法
其中后两个是动态绑定的(多态)。
包访问权限类的main方法,内部类的main方法,可以作为程序的main入口吗?
可以。由于都是public static的,可以认为是全局方法。
多态
final static类型的变量可不可以空白初始化?
final可以修饰:
- final类,表示类不可被继承;
- final方法,表示该方法不可被复写;
- final变量,表示变量的值不可被修改;
- final参数,表示该参数值不可被修改(类似final变量)。
final变量是可以空白初始化的,这样可以根据不同的情况来决定“最终值”,更具灵活性,但要求,该final变量必须在对象初始化的时候赋值(可以在构造器中,也可以在对象初始化代码中)。 然而,如果变量是final static类型的,由于此类变量独立于对象,属于类域,必须在类加载的时候就完成初始化,因此,除非在静态代码块里初始化该变量,否则会编译报错。
为什么有的方法要使用final关键字?
- 设计,即不允许其他人修改
- 效率,final和static修饰的方法不需要动态绑定过程,理论上可以提高效率(允许inline),但实际在现代jvm中inline的策略更激进,jvm如果判断该方法不存在多态,会自动inline,因此对于性能的提升微乎其微,可以忽略。
什么是绑定?什么是前期绑定,什么是后期绑定?
将方法调用和方法主题关联起来。像C语言这种在编译时期即确定关联关系的叫做前期绑定;java等语言支持在运行时确定关联关系,叫做后期绑定、动态绑定、运行时绑定。
什么是协变返回类型
导出类的覆盖方法中可以返回基类的导出类(一般应返回基类的类型)。
多态带来什么好处?
将改变的事物与未变的事物解耦分离:通过动态绑定,调用者(或使用者)可以只与基类通信,可以新增类型,扩展性好。 只有(非static非final非private)普通方法具有多态的特性,类域、静态方法、final方法,都是在编译的时候就确定了的。
父类构造器中调用的方法如果被子类覆盖了,实际调用的是父类的还是子类的方法?
子类的方法,因为发生了动态绑定。务必要注意,此时可能子对象的域还没有初始化,如果在子类的方法中访问这些域,值可能还是不是预期的值。 尽量减少子类和父类的耦合。
用继承表示行为间的差异,用组合表示状态间的差异。
abstract class有什么意义?
目前来看,也就是能防止不正确的new 对象。相对方法来说,可以避免去定义一些dummy方法,但interface提供了多继承的手段。
interface的方法,默认是public还是protect?
public,接口内所有元素都是public。实现该方法的类的对应方法,必须是public。
策略设计模式与适配器设计模式
通过接口,将通用处理集中于某一个类中形成框架,在框架中根据传入不同的对象,实现不同的处理。不同的对象,叫做不同的策略。 适配器设计模式,在策略设计模式之上,原因是对象可能无法直接传入框架,需要先使用适配器来代理该对象,然后将新对象传入适配器;用户看到的是适配器。
如何证明接口中的域是static和final的?为什么要允许接口中定义域呢?
static表示该域为类所有,在类加载时即初始化,因此直接访问 接口名.域名 即可,不需要new对象; final表示终态,不可修改、不可被继承。 接口描述的是对象之间的协议,用于消息传递,因此应该只有方法;但为了表示一些常量信息,允许在接口中定义域来达到定义常量的目的。
interface TestInterface {
int privateVal = 1;
}
public class Parcel {
Parcel() {
System.out.println(TestInterface.privateVal);
}
}
接口中可以嵌套接口吗?若可以,新接口可以是什么访问权限?
可以嵌套。由于接口内所有元素都是public的,所以新接口也是public的。注意,不需要特意加一个public关键字来修饰新接口。
Subscribe via RSS