继承
继承是面向对象思想的特性之一。所谓继承,就是对已有的一个类进行拓展,派生出一个新的类。该类拥有原有类的一切属性与方法,并且在新的类中可以定义新的属性与新的功能。Java中只允许单继承。
继承的一般写法:
在Java中,我们运用关键字extends来表明该类是一个现有类的派生。
Java类的继承一般写法如下:
public class SubClass extends ParentClass{
public SubClass(){
super();
}
}
以上代码表示了SubClass是ParentClass的子类。SubClass会继承ParentClass的属性与方法,同时SubClass还可以根据自身需求进行新功能的拓展。
Object类:
Object类是所有类的父类,任何类都继承于Object类,可以说Object类是继承层次的最顶端,也就是继承层次的根类。一切类都可以使用Object类中的方法。Object类拥有主要方法如下:
(1)Object.clone()方法:
Clone()方法可以复制一个相同的对象给开发人员,调用clone方法相当于又新建了一个对象,该对象的一切属性与母对象相同。同时要进行克隆操作必须实现Cloneable接口。
(2)Object.equals(Object obj)方法:
在Java基础中讲过equals与 == 的不同之处,这边不在进行赘述,Object.equals()方法可以检查一个对象是否与调用这个方法的对象相等。
(3)Object.finalize()方法:
该方法常用来进行垃圾清理(GC操作)。由于JVM底层会自动进行GC操作,因此主动调用该方法在日常的编程中很少使用。
(4)Object.hashCode()方法:
该方法返回对象的哈希值,一般情况下哈希值是由其JVM内存中的地址决定的,不同的对象在内存中有着不同的地址,同样也有着不同的哈希值。
(5)Object.getClass()方法:
该对象可以获取某个实例的Class对象,用到了Java反射机制,具体会在反射一文中详细阐述。获取Class对象之后就可以对其进行一系列操作,如获取类名,判断类型等。
(6)Object.toString()方法:
该方法返回了当前类的信息,用户也可以重写该方法来自定义所要输出的内容。
访问权限修饰符
使用访问修饰符的目的一般是为了保障代码的安全性,提高其可用性。Java将访问权限修饰符分为4个级别,分别是public,protected,default,private。
public:利用该关键字进行修饰表示了最大的访问权限,在这种情况下其所有的内容都是开放的,所有的用户都可以直接进行调用。
protected:利用该关键字进行修饰主要是为了实现对于子类的保护,在这种情况下用户可以访问与其在同一个包(package)下或者是其(无论是否在同一个包内)子孙类的数据成员。
default:利用该关键字进行修饰主要是为了实现包内访问的功能,在这种情况下用户只能访问与其在同一包(package)中的数据成员。
private:利用该关键字进行修饰主要是为了保护某个数据成员,在这种情况下用户只能在自己的类中进行访问。
在通常情况下,Java的外部类都是用public进行修饰,用户也可以不进行修饰。在不进行修饰的情况下,系统默认使用default权限。
final修饰符
final修饰符为非访问修饰符,开发人员可使用该修饰符完成各类操作。
(1)利用final修饰符修饰类:
利用final修饰符修饰类的情况下就表明了该修饰类无法被继承,并且在该类中的方法成员都不会被修改。例如String类就是用final修饰,无法被继承于修改,因此有了之后StringBuffer可修改字符类的出现。
(2)利用final修饰符修饰方法:
利用final修饰符修饰一个方法表明了该类无法被修改覆盖,但是该类可以被继承。
(3)利用final修饰符修饰属性变量:
利用final修饰符修饰一个属性变量表明了该属性一旦经过初始化之后就不可进行更改。并且只能在其定义的过程或者是在构造函数中进行赋值。
super与this关键字
(1)super关键字
super关键字可以在子类中调用基类构造,可以继承基类中同名的方法,可以调用基类的成员,具体案例如下:
public class Test {
static class Parent{
private String str = "Parent";
public Parent() {
}
public void print(){
System.out.println("Parent method");
}
}
static class Child extends Parent{
public Child() {
super(); //调用基类构造
}
public void print(){
super.print(); //继承基类同名方法
System.out.println(super.str); //调用基类成员
}
}
public static void main(String args[]){
Child child = new Child();
child.print();
}
}
(2)this关键字
this关键字在一个类中可以调用类中的属性,还可以调用类中的方法,还有个非常重要的作用就是可以区分局部变量与成员变量,具体案例如下:
public class Test {
private String str;
private Integer num = 10;
public Test(String str) {
this.str = str; //区分局部变量与成员变量
System.out.println(this.num); //调用类中的属性
this.print(); //调用类中的方法
}
private void print(){
System.out.println("print method");
}
}
继承初始化优先级
我们先来看一下如下代码:
public class Test {
static class Parent{
private static final String str1 = print("Parent constant Init");
private String str2 = print("Parent Variable Init");
static{
System.out.println("Parent Static Block");
}
{
System.out.println("Parent Block");
}
public Parent() {
System.out.println("Parent Constructor Init");
}
public static String print(String str){
System.out.println(str);
return str;
}
}
static class Child extends Parent{
private String str1 = Parent.print("Child Variable Init");
private static String str2 = Parent.print("Child Static Variable Init");
static{
System.out.println("Child Static Block");
}
{
System.out.println("Child Block");
}
public Child() {
super();
System.out.println("Child Constructor Init");
}
}
public static void main(String[] args){
Child child = new Child();
}
}
其执行结果如下:
Parent constant Init
Parent Static Block
Child Static Variable Init
Child Static Block
Parent Variable Init
Parent Block
Parent Constructor Init
Child Variable Init
Child Block
Child Constructor Init
综上所示,当实例化一个子类时,首先执行的是父类静态成员属性的初始化以及父类静态代码块内的代码。紧接着是子类静态成员属性的初始化和子类静态代码块内的代码。之后是父类一般成员变量的初始化以及父类非静态代码块中的代码然后才是父类构造器进行构造。紧接着是子类一般成员变量初始化以及子类非静态代码块中的代码,最后才是子类构造器进行构造。
继承的优缺点
(1)优点:
子类可以直接继承父类的属性方法以及对象,减少重复的劳动,提高了代码的可重用性。并且子类可以在原有父类的基础上进行一些个性化的拓展,提高了项目的可拓展性。
(2)缺点:
破坏了封装性,父类与子类之间的耦合性相当高,一旦父类需要更改代码,子类也要随之进行改变,降低了项目的灵活性,且Java只支持单继承,无法实现多继承。
本文参考Core Java一书,并且结合博主的知识心得进行拓展,如有错误之处望大家指正!