大数据Java基础DAY9(面向对象——继承)

目录

代码块

a.局部代码块:  

b.构造代码块:

c.静态代码块

继承

继承概述

继承案列

继承的好处

Java中继承的特点

Java中继承的注意事项

继承中成员变量的关系

super关键字

继承中构造方法的关系

继承中成员方法的关系

方法重写概述

final关键字


代码块

在Java中,使用{}括起来的代码被称为代码块,根据其位置和声明的不同,可以分为局部代码块,构造代码块,静态代码块,同步代码块(到多线程再说)。

a.局部代码块:  

         在方法中出现;限定变量生命周期,及早释放,提高内存利用率。

        在同一个类的同一个方法中,如果存在多个局部代码块,执行顺序是自上而下的

   

public class Test1 {
    public static void main(String[] args) {
           //第一个代码块
        {
            int a=100;
            System.out.println(a);
        }
            //第二个代码块
        {
            int b =200;
            System.out.println(b);
        }
            //第三个代码块
        {
            int c=300;
            System.out.println(c);
        }
    }
}

大数据Java基础DAY9(面向对象——继承)

b.构造代码块:

在类中方法外出现;多个构造方法方法中相同的代码存放到一起,每次调用构造都执行,并且在构造方法前执行。

class Demo{
    //创建一个无参构造方法
    Demo(){
        int a=10;
        System.out.println(a);
    }
    //创建一个构造代码块(定义在类中方法外,用大括号括起来的代码,称为构造代码块)
    {
        int b=20;
        System.out.println(b);
    }
}
public class Test2 {
    public static void main(String[] args) {
        //创建Demo的对象
        Demo demo = new Demo();
        //创建一个局部代码块
        {
            int c=30;
            System.out.println(c);
        }
    }
}

大数据Java基础DAY9(面向对象——继承)

 可以看出当一个类中既存在构造方法又存在构造代码块,在创建对象时,会先执行构造代码块,再执行构造方法,而main方法里还是自上而下执行。

c.静态代码块

在类中方法外出现,并加上static修饰;用于给类进行初始化,在加载的时候就执行,并且值执行一次。

class Demo{
    //创建一个无参构造方法
    Demo(){
        int a=10;
        System.out.println(a);
    }
    //创建一个构造代码块(定义在类中方法外,用大括号括起来的代码,称为构造代码块)
    {
        int b=20;
        System.out.println(b);
    }
    //创建一个静态代码块
    static {
        int d=40;
        System.out.println(d);
    }
}
public class Test2 {
    public static void main(String[] args) {
        //创建Demo的对象
        Demo demo = new Demo();
        //创建一个局部代码块
        {
            int c=30;
            System.out.println(c);
        }
    }
}

大数据Java基础DAY9(面向对象——继承)

 静态代码块优先其他代码块执行,不创建对象也会执行。

最后我们整合一下:

class Demo3{
    Demo3(){
        System.out.println("Demo3的无参构造方法");
    }

    static {
        System.out.println("Demo3中的静态代码块");
    }

    {
        System.out.println("Demo3中的构造代码块");
    }
}
public class Test3 {
    static {
        System.out.println("Test3中的静态代码块");
    }

    public static void main(String[] args) {
        {
            System.out.println("main方法中的局部代码块");
        }

        Demo3 demo3 = new Demo3();  //创建Demo3的对象
    }
}

Demo3类需要创建对象才能访问,所以先走Test3类,Test3中静态代码块优先,再执行main方法里面的。直到创建了Demo3的对象,开始按静态代码块——构造代码块——构造方法的顺序执行。

大数据Java基础DAY9(面向对象——继承)

继承

继承概述

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

b.通过extends关键字可以实现类与类的继承

      格式: class 子类名 extends 父类名 {}  

c.单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类。 有了继承以后,我们定义一个类的时候,可以在一个已经存在的类的基础上,还可以定义自己的新成员。

继承案列

class Father{
    //创建父类,定义成员变量
    String name;
    int age;

    public void sleep(){  //定义一个方法
        System.out.println("睡觉");
    }
}

class Son{
    //创建一个子类,定义成员变量
    String name;
    int age;
    
    public void sleep(){
        System.out.println("睡觉");
    }
}

当我们创建了两个或更多有共同之处的类的时候,发现这样就很麻烦,如上父与子类都有相同的成员变量,都有一个共同的方法,所以我们能利用继承来改进。

改进后:

class Person{  //定义一个人类,提取出父与子的相同处
    String name;
    int age;

    public void sleep(){
        System.out.println("睡觉");
    }
}

class Father extends Person{  //创建父类继承人类
}

class Son extends Father{ //创建子类继承父类

    public void play(){  //创建一个子类特有的方法
        System.out.println("玩游戏");
    }
}

public class Extends1 {
    public static void main(String[] args) {
        //创建父类对象
        Father father = new Father();
        father.sleep();   //父类通过继承能访问Person类的方法

        //创建子类对象
        Son son = new Son();
        son.sleep();   //子类通过继承能访问Person类的方法
        son.play();    //子类也可以访问自身特有的方法
    }
}

大数据Java基础DAY9(面向对象——继承)

 使用继承后,父与子类都能访问Person类的方法,而且子类也能访问自己特有的方法。

继承的好处

a.提高了代码的复用性

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

b.提高了代码的维护性

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

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

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

Java中继承的特点

a.Java只支持单继承,不支持多继承。

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

           class SubDemo extends Demo{}    (正确)

           class SubDemo extends Demo1,Demo2...  (错误)

b.Java支持多层继承(继承体系)

            class A{}

            class B extends A{}

            class C extends B{}

Java中继承的注意事项

a.子类只能继承父类所有非私有的成员(成员方法和成员变量)

            其实这也体现了继承的另一个弊端:打破了封装性

b.子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法。

c.想要初始化子类,必须先初始化父类

d.不要为了部分功能而去继承

继承中成员变量的关系

案例:

class Father2 {  //创建父类
    int a = 40;
    int b =50;
    public void num2() {
        System.out.println(a);
    }
}
class Son2 extends Father2 { //子类继承父类

         int a = 20;
    public void num1() {
        System.out.println(a);
    }

    public void num3(){
        System.out.println(b);
    }
}
public class Extends2 {
    public static void main(String[] args) {
        //创建子类对象
        Son2 son2 = new Son2();
             son2.num1();   //就近原则,输出的应该是Son2中的a
             son2.num2();   //子类中没有该方法,到父类中寻找
             son2.num3();   //子类中没有元素b,去父类寻找
    }
}

大数据Java基础DAY9(面向对象——继承)

结论

在子类方法中访问一个变量

a.首先在子类局部范围找 

b.然后在子类成员范围找

b.最后在父类成员范围找(肯定不能访问到父类局部范围)

d.如果还是没有就报错。(不考虑父亲的父亲…)

super关键字

class Father3{
    int num=30;
}
class Son3 extends Father3{

    int num =40;

    public void show(){
        int num=50;
        System.out.println(num); //可以访问到show方法里面的num
        System.out.println(this.num);  //使用在封装里说的this关键字可以访问到类中的num
    }
}
public class Extends3 {
    public static void main(String[] args) {

        Son3 son3 = new Son3();
        son3.show();
    }
}

如上,我们可以访问到子类方法里面的num,也可以利用this关键字访问子类中方法外的num,那如果我们想访问父类中的num呢,Java里提供了一个关键字:super

(在上面代码子类show方法里加入 System.out.println(super.num);就可以访问父类里面的num)

大数据Java基础DAY9(面向对象——继承)

 super的用法和this区别

                             this代表本类对应的引用。

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

用法(this和super均可如下使用)

a.访问成员变量:

                     this.成员变量        

                     super.成员变量 

b.访问构造方法

                      this(…)      

                      super(…)

c.访问成员方法

                      this.成员方法()    

                      super.成员方法()

继承中构造方法的关系

子类中所有的构造方法默认都会访问父类中空参数的构造方法。

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

例:

class Father4{

    Father4(){
        System.out.println("这是父类中的无参构造方法");
    }
    
    Father4(String s){
        System.out.println("这是父类中的有参构造方法"+s);
    }
}
class Son4 extends Father4{
    Son4(){
        System.out.println("这是子类中的无参构造方法");
    }
    
    Son4(String s){
        System.out.println("这是子类的有参构造方法"+s);
    }
}
public class Extends4 {
    public static void main(String[] args) {
        //创建子类对象
        Son4 son4 = new Son4("User");
    }
}

 大数据Java基础DAY9(面向对象——继承)

当父类中没有无参构造方法:

a.子类通过super去显示调用父类其他的带参的构造方法

例:

class Father4{

    Father4(String s){
        System.out.println("这是父类中的有参构造方法"+s);
    }
}
class Son4 extends Father4{
    Son4(){
        super("FU");
        System.out.println("这是子类中的无参构造方法");
    }

    Son4(String s){
        super("FU");
        System.out.println("这是子类的有参构造方法"+s);
    }
}
public class Extends4 {
    public static void main(String[] args) {
        //创建子类对象
        Son4 son4 = new Son4("User");
    }
}

大数据Java基础DAY9(面向对象——继承)

b.子类通过this去调用本类的其他构造方法

          本类其他构造也必须首先访问了父类构造

例:

class Father4{
    Father4(String s){
        System.out.println("这是父类中的有参构造方法"+s);
    }
}
class Son4 extends Father4{
    Son4(){
        super("FU");
        System.out.println("这是子类中的无参构造方法");
    }
    Son4(String s){
        this();  //使用this关键字,先调用子类的无参构造方法 ,间接的调用父类构造方法
        System.out.println("这是子类的有参构造方法"+s);
    }
}
public class Extends4 {
    public static void main(String[] args) {
        //创建子类对象
        Son4 son4 = new Son4("User");
    }
}

大数据Java基础DAY9(面向对象——继承)

c.一定要注意: super(…)或者this(….)必须出现在第一条语句上, 否则,就会有父类数据的多次初始化

继承中成员方法的关系

子父类中同名和不同名的成员方法

class Father5{
    public void show(){
        System.out.println("父类中的show方法");
    }

    public void show3(){
        System.out.println("父类中的show3方法");
    }
}

class Son5 extends Father5{
    public void show(){
        System.out.println("子类中的show方法");
    }
    public void show2(){
        System.out.println("子类中的show2方法");
    }
}
public class Extends5 {
    public static void main(String[] args) {
        Son5 son5 = new Son5();
        son5.show();  //调用子类的show方法,就近原则
        son5.show2();  //调用子类的show2方法
        son5.show3(); //子类访问show3方法,子类没有去父类中找
    }
}

大数据Java基础DAY9(面向对象——继承)

结论: 通过子类对象去访问一个方法,首先在子类中找,然后在父类中找,如果还是没有就报错。

方法重写概述

子类中出现了和父类中一模一样的方法声明,也被称为方法覆盖,方法复写。

使用特点:

               如果方法名不同,就调用对应的方法

               如果方法名相同,最终使用的是子类自己的

方法重写的应用:

              当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容。

例:

class Father6{
    public void study(String s){
        System.out.println("学习"+s);
    }
}

class Son6 extends Father6{
    public void study(String s){        //重写父类中的study方法
        System.out.println("学习"+s+"中的继承");
    }
    public  void study2(String s){
        System.out.println("学习"+s);  //子类特有的方法
    }
}
public class Extends6 {
    public static void main(String[] args) {
        //创建子类对象
        Son6 son6 = new Son6();

        son6.study("java");   //调用子类的study方法
        son6.study2("大数据");
    }
}

大数据Java基础DAY9(面向对象——继承)

 方法重写的注意事项

a.父类中私有方法不能被重写

b.子类重写父类方法时,访问权限不能更低

c.父类静态方法,子类不能进行重写

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

方法重写(override)是发生在继承关系中子类里的,方法重载(overload)是发生在同一个类中的

重载是方法名一样,参数列表不一样

重写是方法名,参数列表,返回值都一样,实现不一样,叫方法的重写。

final关键字

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

特点:

a.修饰方法,方法不能被重写

例:当我们不想让子类覆盖重写父类中的方法或者功能,只能让子类去使用时,可以使用final

class Father7{
    public final void show(){   //使用final修饰方法
        System.out.println("父类中的show方法");
    }
}

class Son7 extends Father7{
   @Override
    public  void show(){      //子类不能重写,否则报错
        System.out.println("这是子类中的show方法");
    }
}
public class Extends7 {
    public static void main(String[] args) {
        Son7 son7 = new Son7();
        son7.show();
    }
}

大数据Java基础DAY9(面向对象——继承)

 可以看到子类如果重写了父类用final修饰的方法,运行就会报错。

b.修饰类,类不能被继承

大数据Java基础DAY9(面向对象——继承)

c.修饰变量,变量就变成了常量,只能被赋值一次(在构造方法完毕之前赋值即可)

大数据Java基础DAY9(面向对象——继承)

final修饰局部变量

      a. 在方法内部,该变量不可以被改变

      b. 在方法声明上,基本类型和引用类型作为参数的情况

                      基本类型,是值不能被改变

                      引用类型,是地址值不能被改变(该对象堆内存中的值是可以改变的)

      c.final修饰变量的初始化时机

                       在对象构造完毕前即可

面向对象三大特征——封装大数据Java基础DAY9(面向对象——继承)https://blog.csdn.net/qq_52400447/article/details/122520149

上一篇:Java寒假学习Day9:构造器&赋值顺序


下一篇:(Day9)总结