成员变量(包括静态变量和实例变量)与所声明的类型的成员变量绑定,这是静态绑定,编译时就做了绑定。
42、instanceof不是关键字,而是运算符
A instanceof B :判断前一个引用变量A所指的对象是否是B类(或其子类)的实例,保证强制类型转换不会出错。
注意:instanceof运算符前面操作数的编译时类型要么和后面的类相同,要么是后面类的父类,否则编译出错。
43、设计父类遵循的原则:尽量隐藏父类的内部数据(父类属性设成private类型)。
父类中的辅助方法设成private,父类中需要被外部类调用的方法以public修饰,但是如果又不希望子类重写该方法,则再用final修饰。如果希望父类中的某个方法被子类重写,但不希望被其它类访问,则使用protected修饰。
注:尽量不要在父类构造器中调用即被子类覆盖的方法,以免引起麻烦。
//下面的代码引起空指针异常,因为先执行父类构造器,父类构造器中调用test方法实际却是调的子类覆盖的test方法,此时
//子类还没初始化,name值为null,把父类test方法改成private就行了,此时没有构成方法重写,父类构造器中test()直接调用Base类的test方法
public class Sub extends Base {
String name="zpc";
public void test(){
System.out.println("子类重写父类的方法,name字符串的长度"+name.length());
}
public static void main(String[] args){
Sub s=new Sub();
}
}
class Base{
public Base(){
test();
}
public void test(){
System.out.println("将被子类覆盖的方法");
}
}
//下面这个例子可以清晰展示初始化顺序,能更好地理解上面那个例子的过程
public class Sub extends Base {
{
System.out.println("Sub的普通初始化块");
}
static {
System.out.println("Sub的静态初始化块");
}
String name="zpc";
public Sub(){
System.out.println("Sub()的构造函数");
}
public static void main(String[] args){
Sub s=new Sub();
System.out.println("**************");
Sub s2=new Sub();
}
}
class Base{
static {
System.out.println("Base的静态初始化块");
}
{
System.out.println("Base的普通初始化块");
}
public Base(){
System.out.println("Base()的构造函数");
test();
}
public void test(){
System.out.println("将被子类覆盖的方法");
}
}
class Singleton{
//使用一个变量来缓存曾经创建的实例
private static Singleton instance;
//隐藏构造器
private Singleton(){}
//提供一个静态方法返回Singleton的实例
public static Singleton getInstance(){
if(instance==null){
instance=new Singleton();
}
return instance;
}
}
public class TestSingleton {
public static void main(String[] args) {
Singleton s1=Singleton.getInstance();
Singleton s2=Singleton.getInstance();
System.out.println("s1=s2 "+(s1==s2));//s1、s2指向同一个对象
}
}45、final总结
(1)final变量
与普通成员变量不同的是,final成员变量(包括类属性和实例属性)必须由程序员显式初始化, 系统不会对final成员进行隐式初始化。
final修饰的类属性和实例属性能指定初始值的地方如下:
类属性:可在静态初始化块、声明该属性时指定初始值
实例属性:可在非静态初始化块、声明该属性、构造器中指定初始值。
public void fuzhi(final int d){
d=9;//非法,由调用方法时传入的参数完成初始化,不能再赋值
} (2)final方法
final修饰的方法不能被重写,例程见(37),不希望子类重写父类某个方法可以使用final修饰该方法。
(3)final类
final修饰的类不可以被继承。