面向对象进阶

31 阅读6分钟

1.static关键词(用来修饰成员方法和成员变量)

1.1静态变量

  • 被该类的所有对象共享

  • 比如在Student类中static String teachername; 那么可以在ClassTest中通过类名调用,即Student.teachername = "大伟老师";

1.2静态方法

1.区分三种类别

javabean类:用于描述事物的类,如Student,Cat,要写空参构造,全参构造,getter and setter。

测试类: 带有main方法的类,如StudentTest

工具类:帮助我们做一些事情的类,要私有化构造方法(创建工具类的对象没有意义)

工具类的一个代码:


package xzx.staticdemo;

public class ArrayUtil {
    private ArrayUtil(){}

    public static String printArr(int[] arr){
        StringBuilder sb = new StringBuilder();
        sb.append('[');
        for(int i=0;i<arr.length;i++){
            if( i != arr.length-1){
                sb.append(arr[i]+",");
            }else{
                sb.append(arr[i]);
            }
        }
        sb.append(']');
        String result = sb.toString();
        return result;
    }

    public static double getAverage(double[] arr){
        double sum = 0;
        for(int i=0;i<arr.length;i++){
            sum += arr[i];
        }
        return sum/arr.length;

    }
}

1.3 static注意事项

  • 静态方法只能访问静态变量和静态方法
  • 非静态方法可以访问所有
  • 静态方法中没有this关键字的

2. 继承

图片.png

  1. public class Student extends Person{}
  2. 可以提高代码复用性,子类也可以在父类的基础上增加自己独特的功能
  3. java只支持单继承,不支持多继承,但支持多层继承(A可以继承B,B可以继承C)
  4. 每一个都直接或间接的继承于object类(虚拟机自动完成)

2.1 代码实现

图片.png

见Idea extendsdemo

2.2 构造方法的调用

  • 父类中的构造方法不会被子类继承。
  • 子类中所有的构造方法默认先访问父类中的无参构造。(因为有可能用到父类中的数据,父类没有完成初始化的话,就不能使用父类的数据)
  • 子类构造方法的第一行语句默认都是super(),不写也存在,且必须在第一行。
  • 如果想调用父类的有参构造,必须手动写super进行调用。
public class Student extends Person{
    public Student(){//空参构造
        super();  //必须写在第一行
    }

     public Student(){ //带参构造
         super(name,age); //访问父类的带参构造
    }
}

2.3 this、super关键词

image.png

  • 什么时候用this访问本类构造方法呢? 当需要设定默认值的时候
首先Student类中有三个成员变量,分别是age name school
如果创建对象的时候不给学校的值,默认为鲨鲨大学
则空参构造要这么写:
        public Student(){
    this(0,null,"鲨鲨大学");//调用本类其他构造方法,虚拟机也不会再添加super了
    }

3. 多态(对象的多种形态)

3.1 应用场景

  • 在学生管理系统中,一定会有多个角色,给每种角色写一个注册方法是愚蠢的,利用多态可以很好的解决这个问题(Student类和Teacher类继承于Person类,可以 Person p = new Student();

image.png

3.2 调用规则

  • 调用成员变量:编译看左边,运行也看左边
  • 调用成员方法:编译看左边,运行看右边
  • 理解:子类继承父类时,会将父类的成员变量也继承下来,但如果重写方法,会将父类的成员方法覆盖掉。 image.png

3.3 优势及弊端

优势:

image.png

弊端: 不能使用子类的特有功能,还要强转成真正的子类类型,并使用instanceof来防止报错。

package xzx.duotaidemo;

public class Test {
    public static void main(String[] args) {
        Animal a = new Dog();
        a.eat();
        // 多态的弊端:使用a.lookHome()会报错, 根据编译看左边,会先看父类有没有该方法,没有的话会报错
        //解决方案
        //把a变回子类类型就可以了
        if(a instanceof Dog){
            Dog d = (Dog) a;
            d.lookHome();
        }else if(a instanceof Cat){
            Cat c = (Cat) a;
            c.Attack();
        }else{
            System.out.println("没有这个类型");
        }
        //JDK14新特性,如果说a是Dog类型,就强制转换成Dog类型,转换之后的变量名为d
        if(a instanceof Dog d){
            d.lookHome();
        }else if(a instanceof Cat c){
            c.Attack();
        }else{
            System.out.println("没有这个类型");
        }
    }
}

class Animal{
    public void eat(){
        System.out.println("动物在吃东西");
    }
}

class Dog extends Animal{
    public void eat(){
        System.out.println("狗在吃骨头");
    }
    public void lookHome(){
        System.out.println("狗在看家");
    }
}

class Cat extends Animal{
    public void eat(){
        System.out.println("哈基米在吃鱼");
    }
    public void Attack(){
        System.out.println("哈基米在哈气");
    }
}

4.封装

4.1 定义

  • 封装:隐藏对象的属性和实现细节,仅对外公开接口来实现交互。
  • 属性被private封装后,在类的外部想要使用,就要通过getter和setter方法

以下是四种常见的权限:

  • public: 被public修饰的内容在当前项目中都可见,描述公共的,公开的内容
  • default: 对于自己家族中(同一个包中)不是什么秘密,对于其他人来说就是隐私了。
  • private:只在当前类的内部可见,对外部完全隐藏,同一个包的同一类才能访问。
  • protected:继承访问权限。

4.2 包

  • 包就是文件夹。用于管理各种不同功能的java类。
  • 命名规则:公司域名反写+包的作用,全部小写。
  • 使用同一个包的类时,不需要导包。
  • 使用java.lang包时不需要导包,其他情况都需要。
  • 如果同时使用两个包中的同名类,需要用全类名。

如 com.cqupt.xzx.student.Student stu = new com.cqupt.xzx.student.Student()

4.3 final关键字

  • 如果一个方法是规则,那就可以用final来修饰。
  • 字符串类就是一个final类。
  • final 修饰一个基本数据类型,fianl PI = 3.141592653,
  • 但是如果final修饰一个引用类型变量,不能改变的是地址值,对象内部可以改变
image.png

4.4 权限修饰符

  • 实际开发一般只用public和private
  • 成员变量私有,方法公开

image.png

4.5 代码块

4.5.1 局部代码块

局部代码块:用于提前结束变量的周期,用于节省内存空间(用完立马回收),随着计算机硬件的发展,现在已经不用了。

image.png

4.5.2 构造代码块

用于将构造方法中重复的代码抽取出来 写在构造代码块里面。 创建对象时会先执行构造代码块,再执行构造方法。 也渐渐被淘汰了,因为不够灵活(有些构造不想执行这个语句),可以直接写一个方法,然后用的时候调用方法就行。

image.png

4.5.3 静态代码块

  • 格式:static{}
  • 特点:随着类的加载而加载,自动触发,只执行一次。
  • 用处:进行数据的初始化

5. 抽象类

  • 父类person中work方法被子类继承,如果子类忘记重写了,就会有问题(学生和老师的work内容不一致),所以abstract类出现了。
  • 抽象方法所在的类就是抽象类,但是抽象类中可以没有抽象方法。
  • 抽象方法必须重写。
  • 抽象类不能实例化。
  • 抽象类中可以没有抽象方法
  • 抽象类可以有构造方法(作用:创建子类对象时,给属性进行赋值的。)
  • 抽象类的子类要不重写抽象类中所有抽象方法,要么是抽象类。

强制重写格式,要不然每个子类都自己写一个work方法,调用的时候不就炸了吗(比如有些有return或者名字来一个working)

public abstract class  Person{
//抽象方法不用写方法体
    public abstract void work();
}