Java基础语法(五)----面向对象(2) 继承


1、继承概述:

  多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。

   通过extends关键字可以实现类与类的继承   class 子类名 extends 父类名 {} 

   单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类。

   有了继承以后,我们定义一个类的时候,可以在一个已经存在的类的基础上,还可以定义自己的新成员。


2、继承的好处

 * 提高了代码的复用性;

 * 多个类相同的成员可以放到同一个类中;

 * 提高了代码的维护性;

 * 如果功能的代码需要修改,修改一处即可;

 * 让类与类之间产生了关系,是多态的前提;

 * 其实这也是继承的一个弊端:类的耦合性很强。


3、继承的特点

 * Java只支持单继承,不支持多继承。

   一个类只能有一个父类,不可以有多个父类。

   class SubDemo extends Demo{} //ok

   class SubDemo extends Demo1,Demo2...//error

 * Java支持多层继承(继承体系)

   class A{}

   class B extends A{}

   class C extends B{}


4、继承的注意事项

 * 子类只能继承父类所有非私有的成员(成员方法和成员变量),其实这也体现了继承的另一个弊端:打破了封装性

 * Object类 是所有的类的顶层父类,所有类都是直接或间接继承自他

 * 子类不能继承父类的构造方法,但是可以通过super(后面讲)关键字去访问父类构造方法。

   即,构造子类对象时,必须先访问父类构造方法。

 *不要为了部分功能而去继承。


案例:

//父类

public class Person {
	private String name;
	private String sex;
	private int age;
	
	// 父类无参构造方法
	public Person() {
		super();//访问顶层父类object的构造方法
		System.out.println("父类的无参构造方法");
	}
	//父类的有参构造方法
	public Person(String name, String sex, int age) {
		super();//访问顶层父类object的构造方法
		this.name = name;
		this.sex = sex;
		this.age = age;
		System.out.println("父类的有参构造方法");
	}
	
	
	
 }

//子类


public class Student extends Person {

	public Student() {
		super();//访问父类Person的无参构造
		System.out.println("子类的无参构造方法");
	}

	public Student(String name, String sex, int age) {
		super(name, sex, age);//访问父类Person的有参构造
		System.out.println("子类的有参构造方法");
	}
	
    
	
}

//测试类

public class Text {

	public static void main(String[] args) {
		Student stu=new Student();
		Student stu1=new Student("Bob","男",18);
		
	}
}


运行结果:



5、继承中成员变量之间的关系

      在父类中定义一个成员变量;

  1)在子类中定义一个成员变量和父类中成员变量名称不同,然后再在子类中定义一个方法去访问变量,发现变量名不同,访问非常简单;

  2)在子类中再定义一个成员变量,和父类中的成员变量名称一致,然后继续访问。发现访问的是子类的成员变量;子类中的成员变量和父类中的成员变量名称一样,在子类中访问一个变量的查找顺序("就近原则")。

  3)如果我要访问父类的成员变量该怎么办呢?通过回想this来引入super关键字


  ** super关键字:和this关键字很像

          this代表本类对应的引用。

          super代表父类存储空间的标识(可以理解为父类引用)

 # 用法(thissuper均可如下使用)

   * 访问成员变量:

          this.成员变量 

         super.成员变

   * 访问构造方法

          this(…);

          super(…);

  * 访问成员方法

          this.成员方法();

         super.成员方法();




6、 继承中构造方法的关系

  * 子类中所有的构造方法默认都会访问父类中空参数的构造方法,为什么呢?

      因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化。每一个构造方法的第一条语句默认都是:super()

  * 如果父类中没有构造方法呢?

    1、手动给父类加上一个无参构造方法;

    2、调用本类的有参构造;(案例如下)

//父类Animal

public class Animal {

	public String name;
    
	//方法1:给父类加上无参构造
	// public Animal() {
	// super();
	// }

	public Animal(String name) {
		super();
		this.name = name;
		System.out.println("父类的有参数构造执行了");
	}

}

//子类Dog

public class Dog extends Animal {
	String sname;

	public Dog() {

		this("aaa");// 调用本类有参数构造
		System.out.println("本类无参数构造执行了");

	}

	public Dog(String sname) {
		super(sname);
		System.out.println(sname);
		System.out.println("本类的有参数构造执行了");
	}

}


//测试类

public class Test {
	public static void main(String[] args) {
		Dog dog = new Dog();
	}

}


//运行结果

 


// //程序分析:

     Dog dog = new Dog();创建子类对象,且是调用无参构造方法。

     首先执行this("aaa");调用本类有参构造,调用本类有参构造首先要执行父类的有参构造方法。



案例2:

 

class Fu {
	static {
		System.out.println("静态代码块Fu");// 1
	}

	{
		System.out.println("构造代码块Fu");// 2
	}

	public Fu() {
		System.out.println("构造方法Fu");// 3
	}
}
class Zi extends Fu {
	static {
		System.out.println("静态代码块Zi");// 2
	}

	{
		System.out.println("构造代码块Zi");// 5
	}

	public Zi() {
		System.out.println("构造方法Zi");// 6
	}
}


//测试类

  

class Test {
	public static void main(String[] args) {
		Zi zi = new Zi();
	}

}


//运行结果

  

//分析小知识:

 1、静态随着类的加载而加载。

 2、静态代码块、构造代码块、构造方法的执行流程

    静态代码块-->构造代码块-->构造方法

 3、只要有子父关系,肯定先初始化父亲的数据,然后初始化子类的数据。



案例3:

 

        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();  //y就是Z类的一个成员变量,创建Z的对象时要执行该语句。
		Z() {
			System.out.print("Z");
		}
		public static void main(String[] args) {
			new Z(); 
		}
	}

//运行结果:   YXYZ


//分析:

   1) 成员变量有基本类型和引用类型的。

      class Demo {

        //基本类型

        int x = 10;

       //引用类型

         Student s = new Student();

     }

 

   2) 类的初始化过程:

      加载class文件;

     堆中开辟空间,只要有对象的创建,都先要在堆内存中给成员变量开辟空间赋初始值;

     变量的默认初始化,一般引用类型成员变量默认初始值为null,基本数据类型默认初始值不为null(int:0; float:0.0;);

     变量的显示初始化;

     构造代码块初始化;

     构造方法初始化;


   3) 遇到extends,就要知道,先初始化父类数据,然后初始化子类数据。

      要注意是分层初始化。super在这里仅仅表示要先初始化父类数据。



7、继承中成员方法的关系

   当父类和子类出现一模一样的方法(方法名相同、参数列表相同、返回值类型相同)时,就会发生方法的覆盖,也就是方法重写。

      为什么要进行方法重写呢?那是因为子类对父类提供的方法不满意,需要在其基础上进行改进和丰富,那么此时就需要方法重写,重写后子类对象调用该方法时访问重写后的方法。

    

    * 方法重写的注意事项:

       1) 父类中私有方法不能被重写,因为父类私有的方法子类不能继承,因此也就谈不上方法重写;

       2) 子类重写父类方法时,访问权限不能更低,最好一致,权限修饰符号的级别大小 public>protected>缺省>private;

      3) 父类静态方法,子类也必须通过静态方法进行重写。


   * 方法重写与方法重载的区别:

         方法重载要求几个方法的方法名相同,参数列表不同,返回值类型可以不同;

         方法重载则要求方法的声明完全相同(方法名相同、参数列表相同、返回值类型相同),

         且方法重载的前提是要有继承关系。



   案例:学生类和教师类根据各自的特点,对sleep()方法、eat()方法进行了重写

//父类Person

public class Person {
	String name;
	int age;

	public void eat() {

		System.out.println("吃饭");
	}

	public void sleep() {

		System.out.println("睡觉");
	}
}


//学生类Student

public class Student extends Person {

	@Override
	public void eat() {
		System.out.println("学生喜欢吃,海底捞");
	}

	@Override
	public void sleep() {
		System.out.println("学生喜欢白天睡觉,晚上哈皮");
	}

}


//教师类

public class Teacher extends Person {

	@Override      //表示重写
	public void eat() {
		System.out.println("老师喜欢吃面条");

	}

	@Override
	public void sleep() {

		System.out.println("我白天讲课,晚上睡觉");
	}

}

//测试类:

public class Test {
	public static void main(String[] args) {
		Teacher teacher = new Teacher();
		Student student = new Student();
		teacher.eat();
		student.eat();
		teacher.sleep();
		student.sleep();
	}

}

//运行结果


8、final关键字

   final关键字是最终的意思,可以修饰类,成员变量,成员方法;

 * 修饰类,类不能被继承;

 * 修饰变量,变量就成了常量,只能被赋值一次,其值不能被改变;

 * 修饰方法,方法可以被继承,但是不能被重写。
















    











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值