封装、继承、多态是面向对象的三大特征,“继承”最主要的目的是为了实现代码的可复用性。通过父类与子类的继承关系,子类继承了父类的成员函数和成员变量,提高了代码的重复利用率。同时,子类也可以扩展自己特有的成员,丰富功能。
在Java中,类与类之间通过extends 关键字来定义继承关系。Java规定,类之间只能是单继承的关系,子类只能继承一个父类,但是可以实现多个接口。
public class Base {
private String name="base";
public String getName(){
return this.name;
}
public Base(){
}
public Base(String name){
this.name=name
}
}
public class Child extends Base{
public String getName(){
return "child";
}
}
Object
Object是Java中规定的一切类的起源,任何类都需要继承Object,在object 中规定了以下11个方法:toString()
equals(Object object)
hashCode()
getClass()
notify ()
notifyAll()
wait()
wait(long timeout)
wait(long timeout,int nanos)
这11个方法是所有对象都拥有的成员,我们可以继承并进行重写,以实现自己的机制。对这上述11个类,其着重功能点不同,可以按照功能点进行分组如下。
输出字符串
toString()方法的作用是返回该对象的文本描述,默认实现是使用类名@16进制哈希码的形式。比如声明了Point 类,实例化该类的一个对象Point pt=new Point() pt.toString()输出的就为 Point@76f9aa66。
对象间相等性的判断
equals()
hashCode()
在java 中,存在两种不同的变量类型,基本数据类型和对象类型。联系到底层的存储机制,二者的区别在于,基本类型都存储在栈中,对象类型存储到堆中。Java提供了8中基础类型,而同时对于每种基础类型,又以对象的方式提供相应的包装类型。具体如下:byte----Byte
short----Short
int----Integer
long----Long
double----Double
float----Float
char----Char
boolean----Boolean
在判断这两种类型的变量是否相等的问题上,我们应该使用的机制也不同。通常情况下,我们使用 === 来进行比较,在基础类型中,这没有问题,比较的依据是内容相等,则变量等价。但是对于对象类型的变量,这比较的是变量的内存地址,这就意味着,除非是同一个对象,否则不可能相等。在object中,equals 的本质就是==,但是例如Integer、String等类型重写了equals方法,变成了内容的比较。
继承下的一些机制
变量初始化
子类初始化的过程中,先进行父类的初始化,可通过super来调用父类相应的构造方法,没有使用super的情况下,将调用父类的默认构造方法。如果声明了一个子类变量,其实例化顺序如下:类初始化父类初始化开辟类变量内存空间并赋值
执行静态代码段
子类初始化开辟类变量内存空间并赋值
执行静态代码段
变量初始化父类变量开辟空间并赋值
执行父类构造函数
子类变量开辟空间并赋值
子类构造函数
注意,在父类构造方法中不要调用可重写的方法,因为一旦子类进行了重写,调用父类构造方法的时候就会调用子类的方法。而且,此时子类构造方法中,如果引用了子类变量,此时子类变量还未进行赋值操作,为null。
public class Base {
private String name="base";
public String getName(){
return this.name;
}
public Base(){
printName();
}
public void printName(){
System.out.println(name);
}
public Base(String name){
this.name=name;
}
}
public class Child extends Base{
private String name="child";
public String getName(){
return "child";
}
@Override
public void printName() {
System.out.println(name);
}
}
public class main extends GeodataApplicationTest {
@Test
public void extendTest() {
Child child = new Child();
}
}
上述代码输出结果为:
开始测试-----------------
null
测试结束-----------------
静态绑定与动态绑定
子类对象可以赋值给父类引用变量,这叫多态,实际执行的调用的是子类的方法,这叫动态绑定。与之相对的是静态绑定,变量绑定到变量的类型。静态绑定在程序编译阶段即可决定,动态绑定需要在运行时决定。
重载和重写
子类继承父类的public方法,如果在子类中同时对该方法进行了重载,在调用时,会同等看待这两种不同来源的重载方法,依据参数类型进行比较,调用符合度较高的方法。
父子类型转换
子类对象可以赋值给父类型的变量,这样称之为向上转换,但是父类对象不可赋值给子类对象的变量,通过强制转换也不行,也就是不可进行向下转换。
继承实现的机制
Java是静态语言,需要经过编译的过程,经过编译后将原来.java格式的源代码文件转换为.class的文件。JVM通过类加载机制,将.class文件加载到内存中,形成类的数据结构。
在类的数据结构中,会记录父类与子类的关系。