Java从入门到放弃08---代码块/继承/关键字super/继承关系中的变量访问原则/继承中构造方法的关系/方法重写/final关键字

Java从入门到放弃08—代码块/继承/关键字super/继承关系中的变量访问原则/继承中构造方法的关系/方法重写/final关键字

01 代码块

  • 概念概述:在Java中,被一对{}括起来的内容被称为代码块。
  • 分类:根据定义的位置和声明的不同分为:局部代码块,构造代码块,静态代码块,同步代码块。

  • 局部代码块:定义在方法中的代码块。将变量的生命周期限定在一个方法中,能够尽早的释放空间和资源,利于提高内存利用率。
  • 构造代码块:定义在类中方法外。构造代码块在创建对象时执行,优先于构造方法执行。每创建一次对象都会执行一次构造代码块和构造方法。
  • 静态代码块:定义在类中方法外,加static状态修饰符。静态代码块随着类的加载而加载,优先于构造代码块和局部代码块执行,且由于类只加载了一次,因此静态代码块只执行一次。静态代码块中只能访问静态变量。

class Student {
		static {
			System.out.println("Student 静态代码块");
		}
		
		{
			System.out.println("Student 构造代码块");
		}
		
		public Student() {
			System.out.println("Student 构造方法");
		}
	}

	class StudentDemo {
		static {
			System.out.println("StudentDemo的静态代码块");
		}
		
		public static void main(String[] args) {
			System.out.println("我是main方法");
			
			Student s1 = new Student();
			Student s2 = new Student();
		}
	}
运行结果:StudentDemo的静态代码块
			我是main方法
		Student 静态代码块
		Student 构造代码块
		Student 构造方法
		Student 构造代码块
		Student 构造方法


02 继承

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

  • 理解:Java中,子类可以继承父类的非私有化的成员变量,成员方法等。

  • 作用:将各个子类的共性向上抽取为父类,以提升代码的复用(重复利用)性和维护性。

  • 继承的优势:提升了代码的复用性和维护性。

  • 继承的弊端:增加了耦合性。

  • Tip:软件的设计原则:1.高内聚(一个类,单独完成某个功能的能力)2.低耦合(一个类要完成某个功能,需要依赖某些类)

  • 语法:class 子类类名 extends 父类类名{}//表示子类继承了父类


  • 继承的注意事项:
    1. Java只支持单继承,但是支持多层继承。(比如A类既想继承B类又想继承C类,继承关系可表示为:class A extends B {} class B extends C{})(课外拓展:C++也是面向对象的语言,但是C++支持多继承)
    2. 子类只能继承父类的非私有成员和方法。
    3. 构造方法不参与继承,但是可以通过super关键字去访问父类构造方法。如果父类只提供了无参构造方法,子类想要提供有参构造方法,可以通过super();调用父类空参构造,对父类数据进行初始化后,再执行本类的有参构造方法来实现。需要注意的是,如果父类只提供了有参构造方法,在创建子类对象时可以通过super(参数列表);调用父类的有参构造方法对父类进行初始化后,再执行本类的无参构造方法对该类对象进行实例化。

程序示例:

public class ExtendsTest {
    public static void main(String[] args) {
        //使用无参构造方法
        Student student = new Student();
        student.setName("张三");
        student.setAge(18);
        student.learning(student.getName());
        System.out.println("---------------------------------");
        Teacher teacher = new Teacher();
        teacher.setName("李四");
        teacher.setAge(32);
        teacher.teaching(teacher.getName());
        System.out.println("---------------------------------");
        //使用有参构造方法
        Student student1 = new Student("王五",19);
        student1.learning(student1.getName());
        System.out.println("---------------------------------");
        Teacher teacher1 = new Teacher("赵六",38);
        teacher1.teaching(teacher1.getName());
        System.out.println("---------------------------------");
    }
}

class People {//父类
    public String name;
    public int age;

    public People() {
    }

    public People(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

class Student extends People {//子类
    public Student() {//子类的无参构造方法
    super();//该语句是默认执行的,可以不写出
    }

    public Student(String name, int age) {//子类的有参构造方法1,使用super调用父类的有参构造方法
        super(name, age);//该语句不能省略必须写出
    }

    public void learning(String name) {
        System.out.println(name+"的职责是学习");
    }
}
class Teacher extends People{//子类
    public Teacher() {
    }
    public Teacher(String name, int age) {//子类的有参构造方法2,注意:如果需要传入的参数(形参)为父类中的私有变量,下面的代码块会报错。
        super();//默认执行,可以省略
        this.name=name;
        this.age=age;
    }

    public void teaching(String name){
        System.out.println(name+"的职责是教学");
    }
}
运行结果:张三的职责是学习
		---------------------------------
		李四的职责是教学
		---------------------------------
		王五的职责是学习
		---------------------------------
		赵六的职责是教学

03 SUPER关键字

  • super:父类空间的一个标识,可理解为对父类的引用,使用super可以访问父类的数据(成员变量、成员方法、构造方法)
  • 对比this理解:this 是本类空间的一个标识,代表本类的引用,哪个对象调用这个方法,方法中的this就代表这个对象。

04 继承关系中的变量访问原则

  • 遵循就近原则,局部变量(形参)位置>本类的成员位置>父类的成员位置

程序示例:

class Fu{
		public int num = 10;
		public Fu(){
			System.out.println("fu");
		}
	}
	class Zi extends Fu{
		public int num = 20;//成员变量
		public Zi(){//无参构造方法
			System.out.println("zi");
		}
		public void show(){
			int num = 30;//局部变量
			System.out.println(num);//由于没有传参,依据就近原则,先在方法中找局部变量,因此打印局部变量num,30
			System.out.println(this.num);//this是本类空间的标识符,谁调用代表谁,因此打印的是本类的成员变量num,20
			System.out.println(super.num);/super是父类空间标识符,该语打印的是父类空间的成员变量num,10
		}
	}
	class Test {
		public static void main(String[] args) {
			Zi z = new Zi();
			z.show();
		}
	}

05 继承中构造方法的关系

  • 在创建子类对象时,子类中所有的构造方法默认都会访问父类中空参数的构造方法。
  • 存在继承关系后,在初始化子类时,先要完成父类数据的初始化。因为,子类想要继承父类的数据,可能还会使用父类的数据。因此,必须要让父类的构造方法执行,来完成父类数据的初始化,然后再完成自己的数据的初始化。
  • 在每个子类的构造方法的第一行,无论是空参构造还是有参构造都会默认有一条语句(但不显示,也可以自己写出,但是该语句必须放在子类构造方法的第一行):子类中super(); 作用是调用父类的空参构造,先完成父类数据的初始化。父类中的super();语句调用的是object类的空参构造。
  • 如果父类只提供了无参构造方法,子类想要提供有参构造方法,可以通过super();调用父类空参构造,对父类数据进行初始化后,再执行本类的有参构造方法来实现。需要注意的是,如果父类只提供了有参构造方法,在创建子类对象时可以通过super(参数列表);调用父类的有参构造方法对父类进行初始化后,再执行本类的无参构造方法对该类对象进行实例化。
  • 构造方法中this()和super()不能共存。

程序示例1:父类只提供了无参构造方法,子类如何提供给有参构造方法

public class MyTest {
    public static void main(String[] args) {
        Son son = new Son(10);
    }
}
class Father{
    int num=1000;
    public Father() {
        super();//父类构造方法中的super();访问的是object类的构造方法
        System.out.println("这是父类的空参构造");
    }
}
class Son extends Father{
    int b=10;
    public Son() {
        super();//访问父类的无参构造方法,完成父类数据的初始化。
        System.out.println("这是子类的空参");

    }
    public Son(int b) {//传入的参数不能是父类中的私有化变量,否则构造代码块会报错
        super();//调用父类的空参构造,完成父类数据的初始化。
        this.b = b;
        System.out.println("子类有参构造执行了");
    }
}
运行结果: 这是父类的空参构造
         子类有参构造执行了

程序示例2:如果父类只提供了有参构造,如何使用子类的空参构造

public class MyTest {
    public static void main(String[] args) {
        Zi zi = new Zi();
        Zi zi = new Zi(10);
    }
}
class Fu{
    int num=10;
    public Fu(int num) {//父类只提供了有参构造
        super();
        this.num = num;
        System.out.println("父类的有参构造执行了");
    }
}

class Zi extends Fu{
    int num=100;
    public Zi() {
        super(10);//调用父类的有参构造方法对父类进行初始化
        System.out.println("子类的空参构造执行了");
    }

    public Zi(int num) {
        super(num);
        System.out.println("子类的有参构造执行了");
    }
}
运行结果:父类的有参构造执行了
         子类的空参构造执行了
         父类的有参构造执行了
         子类的有参构造执行了	

06 继承中的方法重写(覆盖)

  • 方法重写(覆盖):当子类出现了父类一模一样的方法(方法名,参数列表,返回值类型一致),子类方法会覆盖父类方法。

  • 继承中的方法重写机制便于子类对父类方法的功能进行拓展,既能沿袭父类的方法,又可以实现子类特有的功能。

  • @override可以检查是否发生了方法重写。快捷键ctrl+O

  • 静态方法属于类,不算重写。

  • 方法重写的注意事项:

    1.父类私有的方法,子类无法重写。私有的方法子类无法继承,更不能重写。

    2.子类在重写父类方法时,权限修饰符不能比父类的低,要比父类的高或者一样,最好一样。权限修饰符等级public>protected>缺省的>private

    3.静态方法不参与重写。


程序示例:

public class MyTest {
    public static void main(String[] args) {
        //为什么要有方法重写的这种机制。如果说子类对父类的方法实现不满意,那么子类就可以覆盖他,或者说,子类想要对父类的方法的实现功能进行扩展,也可以使用方法重写的这种机制
        Zi zi = new Zi();
        zi.show();//子类和父类中都有该方法,执行时执行子类的方法
        zi.test();//子类中特有的方法
    }
}
class Fu {
    int num=100;
    public void show(){
        System.out.println("我是父类的show方法");
    }
}
class Zi extends Fu{
    int num=200;
    public void test(){
        System.out.println("我是子类的test方法");
    }
    @override
    public void show() {//子类重写父类中的show方法
        System.out.println("我是子类的show方法");
    }
}
运行结果:我是子类的show方法
        我是子类的test方法

07 final关键字

  • 回顾:常量可以分为字面值常量和自定义常量,常量的命名字母全部大写。

  • final修饰特点
    修饰类: 被修饰的类不能被继承

    final class A
    

    修饰方法: 被修饰的方法不能被重写

    public final void test(){}
    

    修饰变量: 被修饰的变量不能被重新赋值,因为这个量其实已经是一个常量了

    final int NUM=100;
    

    修饰引用数据类型:被修饰的引用数据类型的地址值不能被改变

    final 类名 对象名=new 类名();
    

猜你喜欢

转载自blog.csdn.net/yinyanyao1747/article/details/89331881
今日推荐