Java继承

继承的概念

        继承是面向对象的三大特性之一,三大特性,封装、继承、多态中封装和继承相当于是给多态的实现提供基础。继承的关键字是extends,如果A类是B类的一种或者说A类比B类更具体此时就可以使用继承,将A类称为子类,B类称为父类,子类会继承父类的属性和行为,同时子类会比父类有更具体的功能.

        所有的类如果没有明确给出继承默认都是继承自Object类,也就是说Object类是所有类的父类.

        Java中只支持单继承,一个子类只能有一个父类。但是支持多层继承。

        继承可以减少代码的重复性,增强代码的复用性。

继承的格式

        在继承中子类可以继承父类中public,protected,默认权限修饰的成员方法和成员变量,private修饰的被继承后无法直接访问需要通过间接的方式访问.构造方法不能被继承.

class Animal {
    int i = 1;

    Animal() {
        super();
        System.out.println("父类无参构造");
    }

    public void eat() {
        System.out.println("动物吃食物");
    }

}

class Cat extends Animal {

    Cat() {
        super();
        System.out.println("子类无参构造");
    }

    public void eat() {     //子类可以重写父类的方法
        System.out.println("猫吃鱼");
    }

    public void out() {   //子类可以有自己特有的方法

        System.out.println(i);
    }

}

public class Text {
    public static void main(String[] args) {

        Cat b = new Cat();
        b.eat();
        b.out();
    }
}
/**
输出为: 
父类无参构造
子类无参构造
猫吃鱼
1
 */
需要注意:

        子类不能继承父类的构造方法但是在访问子类无参构造的时候会优先访问父类的无参构造,父类也会先访问父类的父类中的无参构造,直到访问到Object类为止。因为Java是分层进行初始化的.

        子类可以继承父类的成员方法,也可以重写.当子类对象调用方法的时候先检查子类中是否有这个方法,如果没有则到父类中检查.一直向上直到检查到Object类,如果都没有会报错.

重写和重载的区别:

重写在继承中子类定义了和父类中相同的方法名,相同的参数和返回值的方法,此时会覆盖掉父类中的方法.
重载

在同一个类中有多个方法名相同但是却有不同的返回值和参数的方法的情况叫做重载,

调用方法时通过传递给它们的不同参数个数和参数类型来决定具体使用哪个方法。

static静态方法

    在继承中子类可以继承父类的静态的方法,如果父类的方法是静态的子类中定义了相同的方法必须也是静态的;

    因为静态方法是相对于类而言的,可以使用类名直接调用,不需要通过继承去调用,使用时也不推荐使用对象去调用静态的方法,如果子类中定义相同的静态方法此时父类的方法相当于隐藏了而不是被重写了。

 super关键字

        子类可以通过super 调用父类的构造方法.

        super关键字必须出现在子类的构造方法的第一行,不能出现在其他地方.

        如果没有写super()默认系统会给每个子类的构造方法第一行给出一个访问父类无参构造的super().

        当子类构造方法中使用this调用子类中其他构造方法时系统不再默认给出super().

        super还可以用来在子类成员方法中访问父类的成员变量,当子类中定义了和父类相同的变量想访问父类的变量就需要用super。

        同样super可以用来访问父类中的方法,如果子类重写了父类的方法,此时在子类的方法中想调用父类的方法就可以使用super。

         super的使用格式如下:

super():		//访问父类的无参构造
super(...):		//访问的是父类的有参构造括号里需要填写对应的参数
super.方法名()	        //访问父类成员方法
super.成员变量名        //访问父类的成员变量
同时区分this的使用方法:
this.成员变量名			//访问当前类中的成员变量
this() 				//访问当前类中的无参构造
this("") ;			//访问当前类的有参构造,括号里需要填写对应的参数
this.方法名()	    	        //访问当前类中的成员方法

注意:因为子类初始化时必定会先访问父类的无参构造,如果父类中有有参构造但是没有无参构造的时候子类初始化就无法访问父类的无参构造,会报错.

此时可以通过在子类无参构造中使用  super(父类有参构造对应类型的值)  来使子类的无参构造访问父类的有参构造来解决.

或者也可以使用this让子类的无参构造去访问子类中的有参构造从而间接访问父类的有参构造.

但是实际开发不这样使用,实际开发中应该每次都给出无参构造,避免发生此类错误.

如下例子:

class Animal {
	String i;

	// 父类中有有参构造时系统不再默认给出无参构造
	public Animal(String i) {
		super();
		this.i = i;
		System.out.println("父类有参构造方法");
	}
}

class Cat extends Animal {

	Cat() {
		super("随便给"); // 访问父类有参构造
		System.out.println("子类无参构造");
	}
}

class Dog extends Animal {
	public Dog() {
		this("随便给");// 访问本类有参构造间接访问父类有参构造
	}

	public Dog(String i) {
		super(i);
		System.out.println("Dog类的有参构造方法");
	}

}

public class Text {
	public static void main(String[] args) {
		new Cat();
		System.out.println();
		new Dog();

	}
}
/**
 * 输出为: 
父类有参构造方法
子类无参构造

父类有参构造方法
Dog类的有参构造方法
 */

可以看到有参构造方法中也是先加载父类的有参再加载子类的有参,进行分层初始化.

final关键字

这里需要提一下final关键字是因为final表示最终的.在Java中:

被final修饰的类不能被继承.

被final修饰的方法不能被重写.

被final修饰的变量一旦被赋值就无法更改变成了常量.

被final修饰的引用类型其地址值不能被改变.但是在堆内存中的成员变量可以变

如下定义方式:

final class Animal {
	// 被final修饰的类无法继承
	final int a = 1;

	// a=2;被final修饰的变量只能被赋值一次,再次赋值会报错
	public final void eat() {
		// 被final修饰的方法不能重写
	}
}

public class Text {
	public static void main(String[] args) {
		final Animal aa = new Animal();
		// aa=new Animal();被final修饰的引用类型不能变更地址值.
	}
}

注意:在继承中如果不想让父类中的方法被子类重写就可以使用final修饰他.

只有final可以修饰局部变量,被修饰的局部变量会变成常量。

例题分析

class X {
	Y b = new Y();

	X() {
		System.out.print("X");
	}
}

class Y {
	Y() {
		System.out.print("Y"); 
	}
}

public class Z extends X {
	Y y = new Y();

	Z() {

		System.out.print("Z");

	}

	public static void main(String[] args) {
		new Z();
	}
}
当前程序中先看主方法,主方法中创建了Z类的匿名对象,所以要加载Z类,又因为Z类继承自X类所以继续向上先加载X类

再X类当中先创建了Y类的对象所以要先访问Y类的无参构造方法,于是先执行11行输出Y

再回到X类访问X的无参构造执行第五行输出X

然后父类加载完后回到子类子类中又先创建了Y类的对象所以又执行一遍11行输出Y

最后再访问子类Z类的无参构造输出Z

所以最后的结果是输出:   YXYZ

       


阅读更多
文章标签: super final
个人分类: Java
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭