1、Java面向对象的特性

发布时间 2023-10-20 17:04:57作者: tiansiju

面向对象的知识点

构造器

构造器的使用与作用

  • 构造器在创建对象时执行-
  • 构造器常用于完成对象的初始化

构造器的注意事项:

  • 如果不写构造器,java会为类生成一个无参构造器
  • 若我们定义了有参构造器,java就不会帮我们的类生成无参构造器了,此时需要我们自己写一个无参构造器出来

static关键字

作用范围

  1. 类对象和实例对象

    • 类对象:用static关键字修饰,属于类,该类所有对象共享
    • 实例对象:无static关键字,属于实例
  2. 类方法和实例方法

    • 类方法:用static关键字修饰,属于类,该类所有对象共享
    • 实例方法:无static关键字,属于实例

    类方法和实例方法使用时的注意事项:

    • 类方法可以直接访问类对象,但不能访问实例对象
    • 实例方法可以直接访问类对象和实例对象
    • 实例方法中可以使用this关键字,类方法中不能使用this关键字

代码块

  • 类的组成:

    • 代码块的分类:

      1. 静态代码块

        格式:static{...}

        特点:只会在类加载时运行一次,由于类只会加载一次,故静态代码块也只会运行一次

        作用:完成对类的初始化,例如:初始化类变量

        imgs

      2. 实例代码块

        格式:{}

        特点:每次创建对象时,执行实例代码块,并在构造器前执行

        作用:和构造器一样,完成对象的初始化,例如:对实例变量进行初始化赋值

继承

  1. 继承特点

    子类能继承父类的非私有成员变量和方法

  2. 继承后对象的创建

    子类的实例对象是由子类和父类共同完成的

  3. 权限修饰符

    imgs

  4. java中只支持单继承,不支持多继承,但支持多层继承

  5. 方法重写

    imgs

  6. 在子类中访问成员的特点
    在子类中访问成员(变量和方法),是按照就近原则访问的:

    1. 现在子类局部作用域范围找
    2. 然后在子类成员中找
    3. 然后在父类成员范围中找,若父类中还没找到就会报错

    如果子父类中出现了重名成员,则会优先使用子类的,若此时要使用父类成员则需要加上super关键字

  7. 子类构造器

    • 特点
      子类全部的构造器,都会先调用父类的构造器,在执行自己:
      子类构造器在调用父类构造器时,总是默认调用父类的无参构造器

    • 子类如何实现调用父类构造器

      1. 在默认情况下,子类会调用父类的无参构造器,子类构造器的第一行都隐式的写了一行代码:super(),它会调用父类的无参构造器
      2. 如果父类中没有无参构造器,我们必须在子类每个构造器的第一行手写super(参数1, 参数2, ...),用于指定地去调用父类的有参构造器
    • 通过this关键字可以调用同一个类中的其他构造器(兄弟构造器)
      注意:this和super调用构造器时都只能写在第一行,因此有了this调用兄弟构造器就不能有super调用父类构造器,反之亦然

多态

多态是在继承/实现情况下地一种现象,表现为:对象多态、行为多态

  1. 多态的前提

    有继承和实现关系;存在父类引用子类对象;子类重写父类方法

    imgs

    注意:

    • 编译看左边,运行看右边
      ​多态在编译时看等号左边的变量类型,在运行时看右边的实例对象类型
    • java中多态是指对象和行为多态,Java中的成员变量不谈多态
  2. 使用多态的好处

    • 在多态下,右边对象是解耦合的,便于扩展和维护
    • 定义方法时,使用父类类型的形参,可以接受一切子类对象,扩展性更强,更便利
  3. 多态下不能使用子类独有的功能

  4. 多态下的类型转换

    自动类型转换:父类 变量名 =  new 子类();
    强制类型转换:子类 变量名 = new 父类();
    
    • 存在继承/实现关系就可以在编译阶段进行强制类型转换,编译阶段不会报错

    • 运行时,如果发现对象的真实类型和强转后的类型不同,就会报类型转换异常(ClassCastExcaption)的错误出来

      People p = new Teacher();
      Student s = (Student) p;
      Teacher t = (Teacher) p;
      

      如上述代码,Student和Teacher都是继承于People类,变量p的之际类型是Teacher,故第二行在编译是不会报错,但在运行时会报错,第三行则正确

    • 强制转换前,可以使用instanceof关键字,判断当前对象的真实类型,在考虑是否强转。

    • 强制转换能够实现调用子类中的独有功能

final关键字

  • 修饰类:该类不能被继承
  • 修饰方法:方法不能被重写
  • 修饰变量:变量只能被赋值一次

注意: final修饰的基本类型变量的时候,变量存储的数据不能被改变;final修饰的引用类型变量,变量存储的地址不能被改变,地址指向的对象内容可以改变

常量

使用static final修饰的成员变量被称为常量

static final SCHOOL_NAME = "西电";

可读性好,可维护性好;

程序编译时,常量会被“宏替换”:出现常量的地方全部会被替换成其常量的内容,保证在使用常量是不用再查找其内容,性能更好

抽象类(abstract)

  1. 修饰类就是抽象类,修饰方法就是抽象方法
  • 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
  • 抽象类也可以有成员变量、方法,构造器
  • 抽象类不能创建对象,仅作为一种特殊的类,由子类继承并实现
  • 一个类继承抽象类,则该类必须重写抽象类的所有抽象方法,否则该类也必须是抽象类

抽象类的好处:

父类的某些行为必须让子类重写,即每个子类都有改行为,但每个子类的具体情况不一样,父类就可以定义成抽象类,该行为定义成抽象方法,从而交给子类去实现,这样能够更好的支持多态

抽象类的应用场景:模板方法

  1. 定义一个抽象类

  2. 在里面定义两个方法:

    一个是模板方法:把相同的代码放进去

    一个是抽象方法:子类对其进行具体实现

  3. 模板方法建议用final关键字修饰

    imgs

接口(interface)

public interface 接口名
{
	// 成员变量:常量
    // 成员方法:抽象方法
}
  • 接口是不能直接创建对象的;接口需要被类实现(implements)的,实现接口的类称为实现类
  • 一个类可以实现多个接口,实现类实现多个接口,必须重写所有接口的抽象方法,不然就要将该类定义为抽象类
  • 弥补了类只能单继承的不足,一个类可以实现多个接口 让程序可以面向接口编程,这样方便在各个业务之间切换

JDK8开始,接口新增的三种形式的方法:

imgs

接口的注意事项

imgs

内部类

内部类是类中五大成分之一(成员变量、方法、构造器、内部类、代码块),如果以给类定义在另一个类的内部,则成为内部类

  1. 成员内部类(了解)

    ​ 成员内部类相当于一个外部类的成员

    imgs

    imgs

  2. 静态内部类(了解)

    imgs

    imgs

    imgs

  3. 局部内部类(了解)

    是定义在方法中、代码块中、构造器等执行体中的 属于鸡肋语法,看看就好

  4. 匿名内部类(重点)

​ 一种特殊的局部内部类,所谓匿名就是程序员不需要给这个类命名

imgs

imgs

imgs

枚举类

imgs

imgs

泛型

imgs

imgs

imgs

可变参数

  • 可变参数是一种特殊的形式参数,定义在方法、构造器的形参列表处,它可以让方法接收多个同类型的实际参数。

  • 可变参数在方法内部,本质上是一个数组

接下来,我们编写代码来演示一下

public class ParamTest{
    public static void main(String[] args){
        //不传递参数,下面的nums长度则为0, 打印元素是[]
        test();	
        
        //传递3个参数,下面的nums长度为3,打印元素是[10, 20, 30]
        test(10,20,30); 
        
        //传递一个数组,下面数组长度为4,打印元素是[10,20,30,40] 
        int[] arr = new int[]{10,20,30,40}
        test(arr); 
    }
    
    public static void test(int...nums){
        //可变参数在方法内部,本质上是一个数组
        System.out.println(nums.length);
        System.out.println(Arrays.toString(nums));
        System.out.println("----------------");
    }
}

可变参数的注意事项:

  • 一个形参列表中,只能有一个可变参数;否则会报错

  • 一个形参列表中如果多个参数,可变参数需要写在最后;否则会报错