接着上篇文章来,我们现在来看java继承中的构造器。子类不能继承父类的构造器(构造方法或者构造函数),但是父类的构造器带有参数的,则必须在子类的构造器中显式地通过super关键字调用父类的构造器并配以适当的参数列表。如果父类有无参构造器,则在子类的构造器中用super调用父类构造器不是必须的,如果没有使用super关键字,系统会自动调用父类的无参构造器:
class SuperClass {
private int n;
SuperClass(){
System.out.println("SuperClass()");
}
SuperClass(int n) {
System.out.println("SuperClass(int n)");
this.n = n;
}
}
class SubClass extends SuperClass{
private int n;
SubClass(){
super(300);
System.out.println("SubClass");
}
public SubClass(int n){
System.out.println("SubClass(int n):"+n);
this.n = n;
}
}
public class TestSuperSub{
public static void main (String args[]){
SubClass sc = new SubClass();
SubClass sc2 = new SubClass(200);
}
}
运行结果为:
SuperClass(int n) SubClass SuperClass() SubClass(int n):200
然后我们来看其它的一些补充说明。首先java 中若要在子类调用父类的方法,需使用关键字super:
class Animal{ void go(){ System.out.println("animal go"); } } class Dog extends Animal{ void go(){ //调用父类方法 super.go(); } } //驱动函数 public static void main(String[] args){ Dog dog=new Dog(); dog.go(); }//输出animal go
那么我们为什么使用继承呢?从已有的类派生出新的类,称为继承。在不同的类中也可能会有共同的特征和动作,可以把这些共同的特征和动作放在一个类中,让其它类共享。因此可以定义一个通用类,然后将其扩展为其它多个特定类,这些特定类继承通用类中的特征和动作。继承是 Java 中实现软件重用的重要手段,避免重复,易于维护,易于理解。
再来看父类和子类。如果类 B 从类 A 派生,或者说类 B 扩展自类 A,或者说类 B 继承类 A,则称类 A 为"父类",也称为超类、基类,称类 B 为"子类",也称为次类、扩展类、派生类。子类从它的父类中继承可访问的数据域和方法,也可以添加新的数据域和新的方法。定义继承的语法如下:
修饰符 class 子类名 extends 父类名
例如:Shape 类是父类,其子类可以有 Circle 类、Rectangle 类、Triangle 类,等等。关于继承我们需要注意如下几点:
- 子类不是父类的子集,子类一般比父类包含更多的数据域和方法。
- 父类中的 private 数据域在子类中是不可见的,因此在子类中不能直接使用它们。
- 继承是为"是一个"的关系建模的,父类和其子类间必须存在"是一个"的关系,否则不能用继承。
但也并不是所有"是一个"的关系都应该用继承。例如,正方形是一个矩形,但不能让 Square 类来继承 Rectangle 类,因为正方形不能从矩形扩展得到任何东西。正确的继承关系是 Square 类继承 Shape 类 - Java 只允许单一继承(即一个子类只能有一个直接父类),C++ 可以多重继承(即一个子类有多个直接父类)。
再来详细看下super关键字。super 表示使用它的类的父类。super 可用于如下方面:
- 调用父类的构造方法;
- 调用父类的方法(子类覆盖了父类的方法时);
- 访问父类的数据域(可以这样用但没有必要这样用)。
调用父类构造方法语法如下:
super(); 或 super(参数列表);
不过要注意,super 语句必须是子类构造方法的第一条语句。不能在子类中使用父类构造方法名来调用父类构造方法。 父类的构造方法不被子类继承。调用父类的构造方法的唯一途径是使用 super 关键字,如果子类中没显式调用,则编译器自动将 super(); 作为子类构造方法的第一条语句。这会形成一个构造方法链。
我们在静态方法中不能使用 super 关键字。调用父类方法语法如下:
super.方法名(参数列表);
如果是继承的方法,是没有必要使用 super 来调用,直接即可调用。但如果子类覆盖或重写了父类的方法,则只有使用 super 才能在子类中调用父类中的被重写的方法。
再来看下this关键字。this 关键字表示当前对象。可用于:
- 调用当前类的构造方法,并且必须是方法的第一条语句。如:this(); 调用默认构造方法。this(参数); 调用带参构造方法。
- 限定当前对象的数据域变量。一般用于方法内的局部变量与对象的数据域变量同名的情况。如 this.num = num。this.num 表示当前对象的数据域变量 num,而 num 表示方法中的局部变量。
final 的作用随着所修饰的类型而不同。1、final 修饰类中的属性或者变量。无论属性是基本类型还是引用类型,final 所起的作用都是变量里面存放的"值"不能变。这个值,对于基本类型来说,变量里面放的就是实实在在的值,如 1,"abc" 等。而引用类型变量里面放的是个地址,所以用 final 修饰引用类型变量指的是它里面的地址不能变,并不是说这个地址所指向的对象或数组的内容不可以变,这个一定要注意。例如:类中有一个属性是 final Person p=new Person("name"); 那么你不能对 p 进行重新赋值,但是可以改变 p 里面属性的值 p.setName('newName');。final 修饰属性,声明变量时可以不赋值,而且一旦赋值就不能被修改了。对 final 属性可以在三个地方赋值:声明时、初始化块中、构造方法中,总之一定要赋值。2、final修饰类中的方法。作用:可以被继承,但继承后不能被重写。3、final修饰类。作用:类不可以被继承。
java文件被编译成class文件时,在子类的所有构造函数中的第一行(第一个语句)会默认自动添加 super() 语句,在执行子类的构造函数前,总是会先执行父类中的构造函数。在编写代码要注意:
- 1.如果父类中不含 默认构造函数(就是 类名() ),那么子类中的super()语句就会执行失败,系统就会报错。一般 默认构造函数 编译时会自动添加,但如果类中已经有一个构造函数时,就不会添加。
- 2.执行父类构造函数的语句只能放在函数内语句的首句,不然会报错。
在继承关系中,在调用函数(方法)或者类中的成员变量时,JVM(JAVA虚拟机)会先检测当前的类(也就是子类)是否含有该函数或者成员变量,如果有,就执行子类中的,如果没有才会执行父类中的。如下:
public class Start { public static void main(String[] args) { Cat cat=new Cat("Jack","黑色"); cat.eat(); cat.run(); cat.sleep(); } } class Animal { String name; public Animal(){}//必须要写这个构造函数,不然Cat类的代码会出错 public Animal(String name) { this.name=name; } void eat() { System.out.println(name+"正在吃"); } void run() { System.out.println(name+"正在奔跑"); } void sleep() { System.out.println(name+"正在睡觉"); } } class Cat extends Animal { String color; public Cat(String name,String color) { this.name=name; this.color=color; } void eat() { System.out.println(color+"的"+name+"正在吃鱼"); } }
运行结果为:
黑色的Jack正在吃鱼 Jack正在奔跑 Jack正在睡觉
当子类出现与父类一样的函数时,这个被称为 重写 也叫 覆盖。Object类是所有类的直接父类或间接父类,也就是说是所有类的根父类,这个可以运用于参数的传递。如下:
public class Start { public static void main(String[] args) { A a=new A(); B b=new B(); C c=new C(); D d=new D(); speak(a); speak(b); speak(c); speak(d); } // instanceof 关键字是用于比较类与类是否相同,相同返回true,不同返回false //当你不清楚你需要的参数是什么类型的,可以用Object来代替,Object可以代替任何类 static void speak(Object obj) { if(obj instanceof A)//意思是:如果参数是 A 类,那么就执行一下语句 { A aobj=(A)obj;//这里是向下转换,需要强制转换 aobj.axx(); } else if(obj instanceof B) { B bobj=(B)obj; bobj.bxx(); } else if(obj instanceof C) { C cobj=(C)obj; cobj.cxx(); } } } //这里举了四个类,他们的函数都不同,但都是 Object 类的子类 class A { void axx() { System.out.println("Good morning!"); System.out.println("This is A"); } } class B { void bxx() { System.out.println("Holle!"); System.out.println("This is B"); } } class C { void cxx() { System.out.println("Look!"); System.out.println("This is C"); } } class D { void dxx() { System.out.println("Oh!Bad!"); System.out.println("This is D"); } }
运行结果为:
Good morning! This is A Holle! This is B Look! This is C好啦,这次就到这里了。如果感觉不错的话,请多多点赞支持哦。。。