最近在学Java的继承,发现里面还是有很多坑的,所以借此做个笔记巩固学习。下面以问答的形式展现我学习过程的问题。
1.父类与抽象类区别?
抽象类只能对属性或者方法的申明,不能对其实现。而继承这个类的子类一定要实现抽象类的所有方法。注意,抽象类的方法必定都是抽象的。而父类可以抽象也可以非抽象,可以不用重写所有方法(除抽象方法)
我们同样无法实现抽象类的实例化,这是什么意思,见下段代码:
abstract class Person{
public abstract void run();
}
class Student extends Person{
@override//这个相当于注释,编译器可以给你验证@Override下面的方法名是否是你父类中所有的,如果没有则报错
void run(){System.out.println("123");}
}
//在主函数中不可以这样定义
Person a=new Person();
//但是可以这样定义
Person a=new Student();
2.super怎么用的?
首先对于super来说:1.可以用来引用直接父类的实例变量。2.可以用来调用直接父类方法。3.可以用于调用直接父类构造函数。
对于1来说,见如下代码:
class Animal {
String color = "white";
}
class Dog extends Animal {
String color = "black";
void printColor() {
System.out.println(color);// prints color of Dog class
System.out.println(super.color);// prints color of Animal class
}
}
public class TestSuper1 {
public static void main(String args[]) {
Dog d = new Dog();
d.printColor();
}
}
打印结果也是很明显的,就是打印出black 和 white
所以:如果我们打印color属性,它将默认打印当前类的颜色。 要访问父属性,需要使用super关键字指定。
对于2来说,见如下代码:
class Animal {
void eat() {
System.out.println("eating...");
}
}
class Dog extends Animal {
void eat() {
System.out.println("eating bread...");
}
void bark() {
System.out.println("barking...");
}
void work() {
super.eat();
bark();
}
}
class TestSuper2 {
public static void main(String args[]) {
Dog d = new Dog();
d.work();
}
}
所以:如果方法被覆盖就可以使用 super 关键字来指定父类方法。
对于3来说:
class Animal {
Animal() {
System.out.println("animal is created");
}
}
class Dog extends Animal {
Dog() {
super();
System.out.println("dog is created");
}
}
class TestSuper3 {
public static void main(String args[]) {
Dog d = new Dog();
}
}
3.子类没有super是否会默认构造?使用了super是否会改变子类的成员变量?
对于问题一来说,任何子类都会默认构造super,什么意思呢?见如下代码
class Animal {
Animal() {
System.out.println("animal is created");
}
}
class Dog extends Animal {
Dog() {
System.out.println("dog is created");
}
}
public class Test1 {
public static void main(String args[]) {
Dog m = new Dog();
}
}
大家猜猜会出现什么?
运行结果如下:
是不是不可思议?没有使用super,编译器竟然默认有,和构造方法一样。
如何使用super构造呢?
class Person {
int id;
String name;
Person(int id, String name) {
this.id = id;
this.name = name;
}
}
class Emp extends Person {
float salary;
Emp(int id, String name, float salary) {
super(id, name);// reusing parent constructor
this.salary = salary;
}
void display() {
System.out.println(id + " " + name + " " + salary);
}
}
public class Test2 {
public static void main(String[] args) {
Emp e1 = new Emp(1, "ankit", 45000f);
e1.display();
}
}
4.为什么我子类构造方法中有super但是多打印出null?
这就是回到前面的问题了,如果没有super语句,子类会默认构造,也就是说,没有出现构造的方法均会被实现,当然了这个构造就是普通的类名(),否则就会造成null的输出。
如果父类没有无参的构造函数,所以子类需要在自己的构造函数中显示的调用父类的构造函数,即不能使用系统默认的“super()”,而需要显性写出super(xxx)
以下是程序的说明:
public class Main{
public static void main(String[] args){
Ming a=new Ming(101,"JACIN");
System.out.println(a.toString());
Ming b=new Ming(100,"JACKSON",98);
System.out.println(b.toString());
}
}
class Student{
String name;
int num;
Student(int num,String name){
this.name=name;
this.num=num;
}
Student(){
}
Student(String name){
this.name=name;
}
public String toString(){
return this.num+" "+this.name;
}
}
class Ming extends Student{
int num;
String name;
int score;
public Ming(int num,String name){
super(num,name);
}
Ming(int num,String name,int score){
this.num=num;
this.name=name;
this.score=score;
}
public String toString(){
return this.num+" "+this.name;
}
}
这个运行结果会这样:
为什么会出现这样的问题呢?我们的疑惑就来了,super到底会不会改变子类的成员变量。这里的程序少了一步,也就是在Ming中super下面加一句,this的使用,否则会出现null
注意这里使用父类的构造方法,所以会根据父类的初始化来改变!
public Ming(int num,String name){
super(num,name);
this.name=name;
this.num=num;
}