继承
概念:
继承是面向对象最显著的一个特性。
继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。
Java继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,
也可以用父类的功能,但不能选择性地继承父类/超类/基类。
初衷:
这种技术使得复用以前的代码非常容易,能够大大缩短开发周期,降低开发费用。
本质上就想要提高代码的复用性,减少代码的编写。
特点:
--使用extends关键字
--相当于子类把父类的功能复制了一份
--java只支持单继承
--继承可以传递(爷爷,儿子,孙子的关系)
--不能继承父类的私有成员
--继承多用于功能的修改,子类可以拥有父类的功能的同时,进行功能拓展
--像是is a 的关系
特点测试:
package cn.tedu.oop;
//这个类用来测试 继承的 入门案例
public class Test1_Extends {
public static void main(String[] args) {
//创建父类对象测试
Father f = new Father(); f.sleep();
f.eat();
System.out.println( f.skin );
System.out.println( f.country );
//3、 创建子类对象测试
Son s = new Son();
//直接使用了爸爸类的功能!!
s.eat();
System.out.println( s.skin );
System.out.println( s.country );
// System.out.println(s.sifangmoney);//5.1、是父类的私有成员,子类看不见更用不了
//直接使用了爷爷类的功能!!
s.sleep();
}
}
//7、继承可以传递
class Yeye{
public void sleep() {
System.out.println("Yeye...sleep()");
}
}
//创建父类
class Father extends Yeye {
//5、父类的私有成员 子类 无法 继承
private double sifangmoney = 100 ;
String skin ="黄种人" ;
String country = "中国";
public void eat() {
System.out.println("Father...eat()");
}
}
//1、创建子类,通过extends关键字表示继承
//4、java只支持单继承
class Son extends Father{//6、继承的关系是is a的关系,强制要求子类必须 继承父类,否则一无所有 -- 强耦合性!!
//2、相当于子类把父类的功能 通通复制过来了
}
super关键字
--1、可以在子类中,使用父类的功能。通过关键字super调用。
--2、super关键字相当于是一个父类对象的引用。
--3、如果出现在构造方法中,必须是第一条语句。
方法重写
--1、是发生在继承结构中。
--2、在需要修改父类 原有功能时,,才在子类中 发生方法重写。
--3、要求:子类的方法声明/签名 和 父类 一模一样(返回值类型,方法名,参数列表)
继承中变量的使用
想要在子类中,使用父类的count -- 由于已经和子类的变量名同名了,如果想用父类的,必须super.
super关键字,用来表示父类对象的引用。可以在子类中使用父类功能。
package cn.tedu.oop;
//这个类用来测试 继承的使用
public class Test2_UseExtends {
public static void main(String[] args) {
//创建对象测试
Zi zi = new Zi();
zi.show();
}
}
//创建父类
class Fu{
int sum = 10 ;
int count = 30 ;
}
//创建子类
class Zi extends Fu{
int count = 20 ;
public void show() {
int count = 10 ;
System.out.println(count);//10 ,使用了局部变量
System.out.println( this.count );
//20,使用了成员变量。当成员变量和局部变量同名时,想用成员变量就通过this调用
//1、想要在子类中,使用父类的sum -- 可以直接用!
System.out.println( super.sum );
//2、想要在子类中,使用父类的count -- 由于已经和子类的变量名同名了,如果想用父类的,必须super
//3、super关键字,用来表示父类对象的引用。可以在子类中使用父类功能。
System.out.println( super.count );//30,使用了父类变量
}
}
继承中方法的使用
--重写前,使用了 从父类的方法体 。 重写后,使用了子类的方法体
--子类 除了可以继承父类的方法,还可以自己扩展方法
--由于子类的实现方式 和 父类不一样,所以我们可能会 需要修改 原来的功能 -- 方法重写!!!
--重写要求:子类 的 方法声明 和父类一样
--在子类中,使用父类的功能--对父类的功能没有影响
package cn.tedu.oop;
//这个类用来测试 继承的 方法使用
public class Test3_UseExtends {
public static void main(String[] args) {
//创建对象测试
Zi2 zi = new Zi2();
zi.eat();//1、重写前,使用了 从父类的方法体 。 重写后,使用了子类的方法体
zi.study(); //3、使用了 子类 自己特有的方法
}
}
//创建父类
class Fu2{
public void eat() {
System.out.println("爸爸在吃猪肉");
}
}
//创建子类
class Zi2 extends Fu2{
//4、由于子类的实现方式 和 父类不一样,所以我们可能会 需要修改 原来的功能 -- 方法重写!!!
//5、重写要求: 子类 的 方法声明 和父类一样
//6、在工作中,不要擅自打开源代码直接进行修改,可能会引发很多bug。最好继承后重写!!重写并没有影响原有功能!!!
public void eat() { // 方法声明一样
// super.eat(); //7、在子类中,使用父类的功能--想看看对父类的功能有没有影响 -- 没有影响
System.out.println("儿子在喝汤");
}
//2、子类 除了可以继承父类的方法,还可以自己扩展方法
public void study() {
System.out.println("我爱java");
}
}
继承中构造方法的使用
--子类的无参构造中,默认就存在super(),自动找父类的 无参构造
--如果,父类中,根本不存在无参构造了 --只能调用父类 的 含参构造
--建议,无参构造方法 随时提供
--super关键字使用 在 构造方法里 时,必须是一条语句!!
package cn.tedu.oop;
//这个类用来测试 继承的 方构造法使用
public class Test4_UseExtends {
public static void main(String[] args) {
//创建对象测试
Zi3 zi = new Zi3() ;
}
}
//创建父类
class Fu3{
// public Fu3( ) { } // 3、建议,无参构造方法 随时提供
public Fu3(int a) {
System.out.println("父类 构造方法");
}
}
//创建子类
class Zi3 extends Fu3{
// public Fu3( ) { } // 5、构造方法不能被继承!!语法就不对!!
public Zi3() {
//1、子类的无参构造中,默认就存在super(),自动找父类的 无参构造
// super() ;
//2、如果,父类中,根本不存在无参构造了 --只能调用父类 的 含参构造
super(100) ;
//4、super关键字使用 在 构造方法里 时,必须是一条语句!!!神似this
System.out.println("子类 构造方法");
}
}
static关键字
特点:
--可以修饰成员变量,成员方法
--随着类的加载而加载,优先于对象加载
--只加载一次,就会一直存在,不再开辟新空间
--全局唯一,全局共享
--可以直接被类名调用
--静态只能调用静态,非静态可以随意调用
--static不能和this或者super共用,因为有static时可能还没有对象
特点测试:
package cn.tedu.staticdemo;
//这个类用来测试 静态
public class Test5_Static {
public static void main(String[] args) {
//2、静态资源 建议 使用静态方式访问:直接被类名调用
//3、静态资源 优先于 对象加载。没有对象时,静态资源也会第一时间加载进内存。
Person.study();
//创建对象测试
Person p = new Person();
p.name = "熊大";
p.study();
p.coding();
System.out.println( p.name );
System.out.println( p.age );
//4、静态资源 是共享资源 。在多个对象间可以共享。
Person p1 = new Person();
System.out.println( p1.name );//熊大
//5、static不能和this或者super共用,因为加载static时可能还没有对象呢
}
}
//创建Person类
class Person{
//提供普通的 成员变量 成员方法
//1、static 可以修饰成员变量 或者 成员方法
static String name ;
int age ;
static public void study() {
System.out.println("正在学习java");
}
public void coding() {
System.out.println("正在敲代码");
}
}
测试静态的调用关系:静态只能调静态
package cn.tedu.staticdemo; //这个类用来测试 静态 的调用 //总结1: 普通资源怎么调用都可以。 静态资源 只能 调用静态资源。 public class Test6_Static { public static void main(String[] args) { //创建对象测试 Person2 p = new Person2(); p.eat(); } } //创建Person2类 class Person2{ //1、普通资源 能不能 调用 静态资源 ? --- 可以!! String name; public void eat() { game(); System.out.println( age ); } //2、静态资源 能不能 调用 普通资源 ? --- 不可以,静态只能调静态 static int age ; static public void game() { // System.out.println( name ); } }
测试代码块的执行顺序
静态代码块:
随着类的加载而加载,并且只被加载一次,一般用于项目的初始化。
位置是在成员位置 + 作用用来只加载一次并且加载的早
执行顺序:
静态代码块>构造代码块>构造方法>局部代码块
package cn.tedu.staticdemo;
/**
*@author 作者:李强
*@email 邮箱:1435430561@qq.com
* 日期: 2020年5月11日
*/
//测试静态代码块和构造代码块,构造方法,局部代码块的执行顺序
public class Test7_Black {
public static void main(String[] args) {
Student s = new Student();
Student s1 = new Student();
s.say();
}
}
class Student{
//静态代码块
static {
System.out.println("这是静态代码块");
}
//构造代码块
{
System.out.println("这是构造代码块");
}
//构造方法
public Student() {
System.out.println("无参构造方法");
{
System.out.println("无参构造方法的局部代码块");
}
}
//局部代码块
public void say() {
System.out.println("say方法");
{
System.out.println("这是局部代码块");
}
}
}