oop面向对象第三四天:引用类型数组、继承、super || 向上造型、方法的重写和重载、成员变量(实例变量和静态变量)和局部变量

在这里插入图片描述

面向对象第三天:

回顾:

  1. 构造方法:构造函数、构造器、构建器--------复用给成员变量赋值

    • 作用:给成员变量赋初值
    • 与类同名,没有返回值类型(连void)
    • 创建对象时被自动调用
    • 若自己不写构造,默认一个无参构造,若自己写了构造,则不再默认提供
    • 可以重载
  2. this:指代当前对象,哪个对象调用方法它指的就是哪个对象

    this的用法:

    this.成员变量名-------------------------访问成员变量

    当成员变量与局部变量同名时,若想访问成员变量则this不能省略

  3. null:表示空,没有指向任何对象

    ​ 若引用的值为null,则该引用不能进行任何操作了,若操作则发生 NullPointerException空指针异常

  4. 引用类型数组:

    Bomb[] bs = new Bomb[3];
    bs[0] = new Bomb(100,200); //1)new
    bs[1] = new Bomb(200,300);
    bs[2] = new Bomb(300,400);
    System.out.println(bs[0].width); //2)访问属性需打点
    

笔记:

1.引用类型数组:

与基本类型数组的区别:

  • 给数组的元素赋值必须new一个对象
  • 若想访问对象数据必须通过数组元素打点
package oopday9.day03.StudentReference;
/**
 * 基本数据类型(basic data type)默认值为————————0!
 * //声明整形数组arr,包含3个元素,每个元素都是int类型,默认值为0
 * int[] arr = new int[3];//基本数据类型
 * arr[0] = 100;
 *
 *
 * 引用数据类型(reference data type)数组的演示:————————默认值为null!
 * //声明Student类型数组s,包含3个元素,每个元素都是Student型,默认值为null
 * //Student是自己写的,就是引用数据类型:
 * Student[] stus = new Student[3];//创建Student数组对象
 *
 */
public class Student {
    String name;
    int age;
    String address;

    Student(String name, int age, String address){
        this.name = name;
        this.age = age;
        this.address = address;
    }

    void sayHi(){
        System.out.println("大家好,我叫"+name+",今年"+age+"岁了,家住"+address);
    }

    public static void main(String[] args) {
        int[] arr = new int[3];//基本数据类型
        arr[0] = 100;
        System.out.println(arr[0]);

        /* 声明Student引用类型数组s,包含3个元素,每个元素都是Student型,默认值为null
        Student是自己写的,就是引用数据类型: */
        //1.创建Student数组对象
        Student[] stus = new Student[3];
        System.out.println(stus);//【@28d93b30】----------变量存着是地址!!!

        /*
        Student stus1 = new Student("张三",25,"河北");
        stus[0] = stus1;
        上两句同下:
         */
        //2.创建Student对象(即给变量传参赋值的时候)-------注1:只要是引用类型,就得new一个构造方法来传参:Student();
        stus[0] = new Student("张三",25,"河北");
        stus[1] = new Student("李四",26,"佳木斯");
        stus[2] = new Student("王五",27,"山东");
        //注1:【引用类型直接访问数组的元素输出的是地址!】
        System.out.println(stus[0]);//@28d93b30----------数组的元素存着是地址!!!

        //(1)输出第一个学生的名字----------------------注2:【引用类型想访问数组的元素需要通过数组元素打点】
        System.out.println(stus[0].name);//张三

        //(2)修改第2个学生的年龄为24------------------注3:【若想访问具体元素的特有属性(name/age...)先取到想访问的元素,再去打点】
        stus[1].age = 24;

        //(3)第3个学生跟大家问好
        stus[2].sayHi();

        //(4)遍历所有学生
        for(int i=0;i<stus.length;i++){
            System.out.println(stus[i].name);//①输出每个学生的名字
            stus[i].sayHi();//②跟所有学生问好
        }
        

    //内存过程:
    //1.创建了一个Student数组对象:
    // 【变量】保存在【栈中】并且【有自己的地址】-------------------------指向堆中的Student数组对象;
    // 【Student数组对象保存在堆中】,在堆中就有了Student数组对象,【包含数组的所有元素(stus[0]/stus[1]...)】,引用数据类型默认值为null
    //2.创建两个Student对象的同时在堆中又产生了两个,因为是引用类型,
    //  所以在堆中元素保存的是地址【@28d93b30,即内存图中的0x2222】-------指向了Student对象
    //3.当修改第2个学生的age为24时,又因为数组是连续的,基于地址就找到了Student对象(保存着是属性name/age...)中的三个参数!
        
    }
}

在这里插入图片描述

2. 继承:

  • 作用:代码复用

  • 通过extends来实现继承

  • 超类/父类:共有的属性和行为

    派生类/子类:特有的属性和行为

  • 派生类既能访问自己的,也能访问超类的,但超类不能访问派生类的

  • 一个超类可以有多个派生类

    一个派生类只能有一个超类-----------单一继承

  • 具有传递性

  • java规定:构造派生类之前必须先构造超类

    • 派生类的构造方法中若没有调用超类的构造方法,则默认super()调用超类的无参构造方法
    • 派生类的构造方法中若自己调用了超类的构造方法,则不再默认提供

    super()调用超类构造方法,必须位于派生类构造方法的第一行

package oopday9.day03.extends1;
/**
 * 继承:------------------extends关键字
 *
 * 继承格式:
 * class 父类 {
 * }
 *
 * class 子类 extends 父类 {
 * }
 *
 * 继承特点:
 * (1)作用:代码复用
 * (2)通过extends来实现继承
 * (3)超类/父类:共有的属性和行为
 * (4)派生类/子类:特有的属性和行为
 * (5)派生类既能访问自己的,也能访问超类的,但超类不能访问派生类的
 * (6)一个超类可以有多个派生类;一个派生类只能有一个超类-----------单一继承
 * (7)具有传递性
 * (8)java规定:构造派生类之前必须先构造超类
 *
 */
public class Person {//--------可以访问a------(6)一个超类可以有多个派生类;一个派生类只能有一个超类
    int a = 5;
    int b = 6;
    
    Person(){
        System.out.println("我是超类构造");
    }

    void eat(){ }

    public static void main(String[] args) {
        Father f = new Father();
        f.eat();
    }
}


class Father extends Person{//-可以访问b+a
    int b;
    Father() { }
    void eat(){//------方法的重写
        this.a = 6;//因为继承了超类,this默认超类的
        super.b = 7;//访问超类的成员变量
    }
}

class Boy extends Father{//---可以访问b+a+c---(7)具有传递性
    int c;
    void eat(String name){//-----派生类自己的方法
    }
}

3. super:指代当前对象的超类对象

super的用法:

  • super.成员变量名----------------------访问超类的成员变量(了解)
  • super.方法名()---------------------------调用超类的方法----------明天讲
  • super()-------------------------------------调用超类的构造方法
package oopday9.day03;
/**
 *《 super的演示》:
 * super----------指代当前对象的超类对象
 * super的用法:
 * (1)super.成员变量名----------------------访问超类的成员变量(了解)
 * (2)super.方法名()------------------------调用超类的方法
 * (3)super()------------------------------调用超类的构造方法
 *
 * java规定:构造派生类之前必须先构造超类:
 * -派生类的构造方法中若没有调用超类的构造方法,则默认super()调用超类的无参构造方法
 * -派生类的构造方法中若自己调用了超类的构造方法,则不再默认提供
 *      -super()调用超类构造方法,必须位于派生类构造方法的第一行
 *
 *
 * 例:下面程序中,为什么会先输出【超类构造方法】,再输出【派生类构造方法】?
 * 原因:在main中,new了一个Boo对象,所以先调用Boo的无参构造,在Boo无参构造中:
 *      若不写super有参构造,则在Boo的无参构造里第一行默认有【super();】无参构造,
 *      此时会调用超类Aoo的无参构造先输出:【超类构造方法】,再输出:【派生类构造方法】
 */
public class SuperDemo {
    int c = 5;
    SuperDemo(int a){
    }



    public static void main(String[] args) {
        Boo o = new Boo();
        int a = 9;
        int b = 10;
    }
}


class Aoo extends SuperDemo{
    Aoo(){
        /* ↓↓↓↓↓↓↓重要重要重要重要重要重要重要重要↓↓↓↓↓↓↓↓ */
        /** 若超类中为有参构造【 SuperDemo(int a){ } 】,
           则在派生类的构造中必须写:【super(3);】有参构造,且位于第一行!
           否则会报错,但不会影响Boo报错,因为Boo默认调用的Aoo的无参构造---Boo是间接继承了SuperDemo,! */
        super(3);//----------------------1.必须位于第一行!!
        super.c = 15;//super.成员变量名------2.访问超类的成员变量
        System.out.println("我是超类构造方法");
    }
    void show(){
        System.out.println("我是超类自己写的方法");
    }
}



class Boo extends Aoo{
    Boo(){
        //--------自己不写系统会默认加的!!!!!
        super();//即使没有这句话,但------------系统也默认用:【super();】调用的超类的无参构造方法!!
        super.show();//super.方法名()---------3.调用超类的方法

        System.out.println("我是派生类构造方法");
        //super();//编译错误,-----super()-----4.调用超类构造方法,必须位于派生类构造方法的第一行!!
    }
}

精华笔记:

1、引用类型数组:

与基本类型数组的区别:
	给数组元素赋值必须new一下
	若想访问对象数据必须通过数组元素打点

2、继承:

  • 作用:代码复用

  • 通过extends来实现继承

  • 超类/父类:共有的属性和行为

    派生类/子类:特有的属性和行为

  • 派生类既能访问自己的,也能访问超类的,但超类不能访问派生类的

  • 一个超类可以有多个派生类

    一个派生类只能有一个超类-----------单一继承

  • 具有传递性

  • java规定:构造派生类之前必须先构造超类

    • 派生类的构造方法中若没有调用超类的构造方法,则默认super()调用超类的无参构造方法
    • 派生类的构造方法中若自己调用了超类的构造方法,则不再默认提供

    super()调用超类构造方法,必须位于派生类构造方法的第一行

3、super:指代当前对象的超类对象

super的用法:

  • super.成员变量名----------------------访问超类的成员变量(了解)
  • super.方法名()---------------------------调用超类的方法----------明天讲
  • super()-------------------------------------调用超类的构造方法

补充:

1.引用类型数组:
与基本类型数组的区别:

  • 给数组元素赋值必须new一下
  • 若想访问对象数据必须通过数组元素打点

2.继承意味着代码虽然我没有写,但也属于我,只是没有写在一起而已
3. 泛化:将共有的抽出来的过程,泛化是设计层面的概念,从代码实现层面来说咱们就是继承,泛化就是继承
4. 继承要符合is a(是一个)的关系

在这里插入图片描述

回顾:

1、引用类型数组:

  • 给元素赋值new一下
  • 访问数据需通过数组元素打点
Student[] s = new Student();
s[0] = new Student("张三",25,"河北");
System.out.println(s[0].move);

2、继承:

  • ​ 代码复用,
  • 通过extends继承
  • 超类:共有的 ; ;派生类:特有的
  • 派生类可以访问派生类自己的+超类的,超类只能访问超类自己的
  • 单一继承
  • 传递性

java规定:构造派生类之前必须先构造超类

  • 1.派生类构造中若自己不调超类构造,则默认super()调超类无参构造
  • 2.派生类构造中若自己调用了超类构造,则不再默认提供
    -----super()调用构造方法必须位于派生类构造方法的第一行

3、super:指代当前对象的超类对象
super用法:

  • super.成员变量名---------------------------访问超类的成员变量
  • super.方法名()-------------------------------调用超类的方法--------一会讲
  • super()-----------------------------------------调用超类的构造方法

面向对象第四天:

笔记:

1、向上造型:前提是继承

  • 超类型的引用(变量)指向了派生类的对象------------------------例:Animal o = new Tiger();
  • 引用能"点" 出来什么,看引用(o:即变量)本身的类型----------例:【o.Animal类中的东西】
1.何时向上造型???
---当多重角色能干的事是一样的,可以将多种角色造型到超类型数组中,统一访问。

2.向上造型的意义:--------实现代码复用
当多种角色能干的事是一样的,可以将那多种角色造型到超类数组中,统一访问
package oopday9.day04.upload;
public class Aoo {
    int a;
    void show(){

    }
    Aoo(){
        System.out.println("我是超类");
    }
}

package oopday9.day04.upload;
public class Boo extends Aoo{//还默认包含Aoo的a和show()
    int b;
    void test(){

    }
    Boo(){
        System.out.println("我是派生类");
    }
}

package oopday9.day04.upload;
//向上造型的演示
public class UploadDemo {
    public static void main(String[] args) {
        Aoo o1 = new Aoo();
        o1.a = 1;
        o1.show();
//        o1.b;  //---------编译错误,超类的引用不能【点】出派生类的,能点出来什么,看引用的类型
//        o1.test();


        Boo o2 = new Boo();
        o1.a = 1;//---------正确。派生类的引用可以【点】出超类的
        o1.show();
        o2.b = 2;
        o2.test();


        Aoo o3 = new Boo();//!向上造型 一个超类型的引用(o3)指向了派生类
        o3.a = 3;
        o3.show();
//        o3.b = 4; //------编译错误  超类的引用(o3)不能点出派生类的,能点出来什么,看引用的类型
//        o3.test();//编译错误,能点出来什么,看引用的类型

    }
}

2、方法的重写(override/overriding):重新写、覆盖

  • 发生在父子类中,方法名相同,参数列表相同
  • 重写方法被调用时,看对象的类型()------------这是规定,记住就OK

当派生类觉得超类的行为不够好时,可以重写

package oopday9.day04.override;
import oopday9.day04.Person;
import oopday9.day04.Student;
/**
 * 《方法的重写(override/overriding)》
 * 1、概念:重新写(当派生类觉得超类的行为不够好时,可以重写)
 *
 * 2、规定:
 *     -(1)发生在父子类中,方法名相同,参数列表相同
 *     -(2)重写方法被调用时,看对象的类型()
 *
 * 3、规则:两同 两小 一大
 * 两同: 方法名与参数列表 和 父类方法保持一致
 * 两小:
 *     子类方法的返回值类型 <= 父类方法的返回值类型。
 *     子类方法抛出的异常类型 <= 父类方法抛出的异常类型
 *      注意1:这里的<=说的是继承关系,不是值的大小
 *      注意2:如果父类方法的返回值类型是void,子类保持一致即可
 *      注意3:子类不可以重写父类的私有方法,还是因为不可见
 * 一大: 子类方法的修饰符权限 >= 父类方法的修饰符权限
 *
 * 4、意义:是在不修改源码的前提下,进行功能的修改和拓展(OCP原则:面向修改关闭,面向拓展开放)
 *
 */
public class Restaurant {
    void show(){
        System.out.println("做中餐");
    }
    double test(){ return 0.0; }
    Student say(){ return null; }

    public static void main(String[] args) {
        Aoo o = new Aoo();
        //---------2、(2)重写方法被调用时,看【引用(o:即变量)new出来】对象的类型(Aoo)
        //【超类中的doing()方法,只是为了能点出来。若超类和派生类都有该方法,则调用派生类的;若派生类中没有则调超类的】
        o.doing("0"); //调用的是------>Boo的doing()
        
        Boo o2 = new Boo();
        o2.doing("1");//调用的是------>Boo的doing()
    }
}


class Aoo extends Restaurant{
                //(1)还是想做中餐,不需要重写
    void show(){//(2)我想改做西餐----------------需要重写(只写西餐)
        System.out.println("做西餐");
    }
//    void show(){//(3)想在中餐基础上+西餐--------需要重写(先super中餐,再加入西餐)
//        super.doing();
//        System.out.println("做西餐");
//    }
    
    //int show(){ return 5; } //编译错误,子类方法的返回值类型 <= 父类方法的返回值类型。
    //int test(){ return 0; } //编译错误,基本数据类型此时不符合大小原则,必须为double
    //Person say(){ return null; } //编译错误,在派生类中重写方法为引用类型时必须:<= 派生类


    void doing(String r){
        System.out.println("我是Aoo中自己写的方法");
    }
}

class Boo extends Aoo{
    void doing(String r){
        System.out.println("我是Boo中重写Aoo的方法");
    }
}

3、重写与重载的区别:重点(常见的面试题)

  • 重写:发生在父子类中,方法名相同,参数列表相同

    一般用于在派生类中修改超类的方法

  • 重载:发生在同一类中,方法名相同,参数列表不同

    是完全不同的方法,只是方法名相同而已

重写与重载的区别:重点(常见的面试题)

&&重写:发生在父子类中,方法名相同,参数列表相同;一般用于在派生类中修改超类的方法
规定:重写方法被调用时,看对象的类型(例:超类是void do(){}  当超类中重写方法被调用时,派生类中必须写成和超类一样:super.do();)
原则:两同,两小,一大
两同:签名(方法名和参数)相同
两小:①派生类方法的返回值类型必须 <= 超类方法;②派生类方法抛出的异常必须<=超类方法;
一大:派生类的访问权限必须>=超类方法

&&重载:发生在同一类中,方法名相同,参数列表不同;是完全不同的方法,只是方法名相同而已,对于返回值类型并没有要求。

1、变量:------成员变量(实例变量和静态变量) 和 局部变量

可以改变的数,称为变量。在Java语言中,所有的变量在使用前必须声明。

一般通过“变量类型 变量名 = 变量值 ;”这三部分来描述一个变量。如:int a = 3 ;

变量的使用原则:就近原则,即尽量控制变量的使用范围到最小

在这里插入图片描述

(1)变量的默认值测试:
创建包: cn.tedu.basic
创建类: TestVariable1.java

package cn.tedu.design;
/*本类用于测试各种类型变量的默认值*/
public class TestVariable1 {
        static String name;
        static byte b;//整数类型默认值都是0
        static short c;
        static int d;
        static long e;
        static float f;//小数类型的默认值是0.0
        static double g;
        static char j;//char类型的默认值是\u0000
        static boolean h;//boolean类型的默认值是false

        public static void main(String[] args) {
            System.out.println(name);//null,引用类型的默认值
            System.out.println(b);
            System.out.println(c);
            System.out.println(d);
            System.out.println(e);
            System.out.println(f);
            System.out.println(g);
            System.out.println(h);
            System.out.println(j);
            System.out.println(h);
        }
    }

2、成员变量(实例变量和静态变量)--------写在类中,方法外(有默认值)

位置:定义在类里方法外
注意:不用初始化,也会自动被初始化成默认值
生命周期:整个类中,类消失了,成员变量才会释放

分为:
1(1)实例变量:①无static修饰属于对象②存储在堆中③有几个对象就有几份④通过引用打点来访问
		   -⑤例:类中有一个变量:int num

(2)静态变量:①由static修饰属于类   ②存储在方法区中③只有一份④常常通过类名点来访问

3、局部变量--------方法中(没有默认值)

位置:定义在方法里或者方法的声明上
注意:必须手动初始化来分配内存.:int i = 5;或者int i; i = 5;
生命周期:随着方法的调用而存在,方法运行完毕就释放了

4、成员变量 与 局部变量区别:

成员变量:写在类中,方法外的。可以在整个类中访问。有默认值。
局部变量:写在方法中的(包括方法的参数)。只能在当前方法中访问。没有默认值。
【注:方法中的局部变量没有默认值,作为参数的局部变量有默认值。】

在这里插入图片描述

(1)局部变量与成员变量测试:

1.
package oopday9.day04.CyJb;
import java.util.Arrays;
/**
 * 成员变量:写在类中,方法外的。可以在整个类中访问。有默认值。
 * 局部变量:写在方法中的(包括方法的参数)。只能在当前方法中访问。没有默认值。
 *        【注:方法中的局部变量没有默认值,作为参数的局部变量有默认值。】
 */
public class Doo {
    int a;//--------------------成员变量(整个类中访问),有默认值
    public static void main(String[] args) {
        int d;
        System.out.println(Arrays.toString(args));
        //System.out.println(d);//编译报错
        Eoo o = new Eoo();
        o.show(2);
    }
}

class Eoo extends Doo{
    /**
     * 为什么局部变量c没有默认值,而作为方法的参数的局部变量b却有?
     * 答:
     * 局部变量b也没有默认值,但是当new一个对象时会传参(见上面main中的new对象↑),
     * 就自然给局部变量b赋值初始化了【o.show(b: 2);】,所以在方法里打印b的值时不会编译报错。
     *
     */
    void show(int b){//----------局部变量b(当前方法中访问)和main方法里的局部变量类似,详情见该包的图片
        int c;//-----------------局部变量c(当前方法中访问):只声明了没有初始化,没有默认值
        System.out.println(a);
        System.out.println(b);
        //System.out.println(c);//编译报错
    }
}






2.
创建包: cn.tedu.basic
创建类: TestVariable2.java

package cn.tedu.oop;
/**本类用于测试变量的使用*/
public class TestVariable2 {
    //2.定义成员变量:
    //1)位置:类里方法外
    //2)无需手动初始化,会自动赋予对应类型的默认值
    //3)作用域:在整个类中生效,类消失,变量才会消失
    static int count;
   
    //3.变量有一个使用的原则:就近原则
    static int sum = 200;
    public static void main(String[] args) {
        //1.定义局部变量:
        //1)位置:在方法里/局部代码块里
        //2)必须手动初始化
        //3)作用域:在方法/局部代码块中,对应的代码执行完局部变量就被释放
        int sum = 100;//定义在方法中的局部变量sum
        System.out.println(sum);//变量的就近原则:使用的都是自己附近的变量,100
        System.out.println(count);
       
        for (int i = 0; i < 10; i++) {//局部变量i只能在循环中使用
            System.out.println(i);
        }
        //System.out.println(i);//报错:无法引用变量i:i cannot be resolved to a variable
    }
}

精华笔记

1、向上造型:前提是继承

  • 超类型的引用(变量)指向了派生类的对象------------------------例:Animal o = new Tiger();
  • 引用能"点" 出来什么,看引用(o:即变量)本身的类型----------例:【o.Animal类中的东西】

2、方法的重写(override/overriding):重新写、覆盖

  • 发生在父子类中,方法名相同,参数列表相同
  • 重写方法被调用时,看对象的类型------------这是规定,记住就OK

当派生类觉得超类的行为不够好时,可以重写

3、重写与重载的区别:-----------常见面试题
重写(override):发生在父子类中,方法名相同,参数列表相同
重载(overload):发生在同一类中,方法名相同,参数列表不同

补充:

1.向上造型的意义:--------实现代码复用

当多种角色能干的事是一样的,可以将那多种角色造型到超类数组中,统一访问
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
面向对象编程(Object-Oriented Programming,OOP)是一种编程范型,它将现实世界中的事物抽象成一个个独立的对象,并在程序中描述这些对象之间的关系和交互。面向对象编程具有高度的模块化、可重用性、可维护性、可扩展性等优点,是目前广泛使用的编程方法之一。 面向对象编程的核心概念包括类和对象、继承、多态、抽象类、接口等。 1. 类和对象 类是一种抽象的数据类型,它描述了一类具有相同属性和方法的对象。对象则是类的实例,它具有类所定义的属性和方法。 2. 继承 继承是指在一个类的基础上创建一个新类,新类包括原有类的所有属性和方法。原有类称为父类或基类,新类称为子类或派生类。子类可以继承父类的属性和方法,也可以重写父类的方法或添加新的方法。 3. 多态 多态是指同一种方法或操作可以在不同的对象上执行,产生不同的结果。多态可以实现代码的通用性和灵活性,使得程序更加容易扩展和维护。 4. 抽象类 抽象类是一种不能被实例化的类,它只定义了一些抽象的方法,而没有具体实现。抽象类通常用于定义一些基本的操作,具体的实现则由子类来完成。 5. 接口 接口是一种规范,它定义了一组方法和属性的集合,但没有具体实现。接口通常用于描述一个类应该具有哪些方法和属性,具体的实现则由实现该接口的类来完成。 面向对象编程的原则包括开闭原则、单一职责原则、里氏替换原则、依赖倒置原则、接口隔离原则等。这些原则可以帮助我们设计出更加健壮、可维护、可扩展的程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值