面向对象

面向对象

 

理解“万事万物皆对象”

  1. 在Java语言范畴中,我们都将功能、结构等封装到类中,通过类的实例化,来调用具体的功能结构

    Scanner,String等

    文件:File

    网络资源:URL

    1. 涉及到Java语言与前端html、后端数据库交互时,前后端的结构都体现为类、对象

 

方法的重载(overload)

  1. 定义:在同一个类中,允许存在一个以上的同名方法,只要他们的参数个数或者参数类型不同即可。

  2. 举例:Arrays类中重载的sort() /binarySearch()

  3. 判断是否是重载:跟方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系!

 

可变个数形参的方法

  1. jdk 5.0 新增的内容

  2. 具体使用

    • 可变个数形参的格式,数据类型 ... 变量名

      public void show(String ... strs){
         System.out.println("show String ... strs");
      }
    • 当调用可变个数形参的方法时,传入的参数个数可以是:0个,1个,2个,。。。

    • 可变个数形参的方法与本类中方法名相同,形参不同方法之间构成重载

    • 可变个数形参的方法与本类中方法名相同,形参类型也相同的数组之间不构成重载。换句话说,二者不能共存

      public void show(String ... strs){
             System.out.println("show String ... strs");
        }

      //   public void show(String[] strs){
      //
      //   }
    • 可变个数形参在方法的形参中,必须声明在末尾

      public void show(int i, String... strs){

      }
    • 可变个数形参在方法的形参中,最多只能声明一个可变形参

      //    public void show(int ... ints, String... strs){
      //
      //   }

       

权限修饰符

 

 

 

对于class的权限修饰符只可以用public和default(缺省)。

  • public类可以在任意地方被访问

  • default类只可以被同一个包内部的类访问

 

this关键字

this调用构造器

    1. 我们在类的构造器中,可以显式的使用“this(形参列表)”方式,调用本类中指定的其它构造器
2. 构造器中不能通过“this(形参列表)”方式调用自己
3. 如果一个类中有n个构造器,则最多有n-1 个构造器中使用了“this(形参列表)”    
  1. 规定:“this(形参列表)”必须声明在当前构造器的首行

  2. 构造器内部,最多只能声明一个“this(形参列表)”,来调用其他的构造器

 

方法的重写

  1. 子类重写的方法的方法名和形参列表与父类中被重写的方法的方法名和形参列表相同

  2. 子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符

    • 特殊情况:子类不能重写父类中声明为private权限的方法

  3. 返回值类型

    • 父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void

    • 父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型可以是A类型或A类型的子类

    • 父类被重写的方法的返回值类型是基本数据类型(比如:double),则子类重写的方法的返回值类型必须是相同的基本数据类型(double)

  4. 子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型

子类和父类的同名同参数的方法要么都声明为非static的(考虑重写),要么声明为static的(不是重写)

 

super关键字

使用属性和方法

  1. 我们可以在子类的方法和构造器中,通过使用"super.属性"或"super.方法"的方式,显式的调用 父类中声明的属性或方法。但是,通常情况下,我们习惯省略"super."

  2. 特殊情况,当子类和父类定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显式的 使用"super.属性"的方式,表明调用的是父类中声明的属性

  3. 特殊情况,当子类重写父类中的方法时,我们要想在子类中调用父类中声明的方法,则必须显式的 使用"super.方法"的方式,表明调用的是父类中被重写的方法

使用构造器

  1. 我们可以在子类的构造器中显式的使用"super(形参列表)"的方式,调用父类中声明的指定的构造器

  2. super(形参列表)"的使用,必须声明在子类构造器的首行

  3. 我们在类的构造器中,针对"this(形参列表)"或"super(形参列表)"只能二选一,不能同时出现

  4. 在构造器的首行,没有显式的声明"this(形参列表)"或"super(形参列表)",则默认调用的是父类中空参的构造器

  5. 在类的多个构造器中,至少有一个类的构造器中使用了"super(形参列表)",调用父类中的构造器

 

子类对象实例化的全过程

  1. 从结果上看:(继承性)

    子类继承父类以后,就获取了父类中声明的属性或方法

    创建子类的对象,在堆空间中,就会加载所有父类中声明的属性

  2. 从过程来看:

    当我们通过子类的构造器创建子类对象时,我们一定会直接或间接的调用其父类的构造器,进而调用父类的父类的构造器,。。。

    直到调用了java.lang.Object类中的空参的构造器为止。正因为加载过所有的父类的结构,所有才可以看到内存中有

    父类的结构,子类对象才可以考虑进行调用

明确:虽然创建子类对象时,调用了父类的构造器,但是自始至终就创建过一个对象,即为new的子类对象。

 

多态性

  1. 我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类方法

    总结:编译,看左边;运行:看右边

  2. 多态性的使用前提:① 类的继承关系 ② 方法的重写

  3. 对象的多态性:只适用于方法,不适用于属性(编译和运行都看左边)

注:多态是运行时行为

有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法。子类特有的属性和方法不能调用

如何调用子类中特有的属性和方法

可以使用强制类型转换符,但可能会出现ClassCastException的异常,此时就需要使用instanceof关键字进行类型判断

if( p1 instanceof Woman){
           Woman w1 = (Woman) p1;
           w1.shopping();
           System.out.println("************Woman****************");
}
if( p1 instanceof Man){
           Man m2 = (Man) p1;
           m1.earnMoney();
           System.out.println("************Man****************");
}

 

static关键字

按是否使用static修饰,又分为:静态属性 vs 非静态属性(实例属性)

实例变量:我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性。当修改其中一个对象中的非静态属性时,不会导致 其他对象中同样的属性值的修改

静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量。当通过某一个对象修改静态变量时,会导致其他对象调用此静态变量时,是修改过了的。

static修饰属性的其他说明:

  1. 静态变量随着类的加载而加载。可以通过"类.静态变量"的方式进行调用

  1. 静态变量的加载要早于对象的创建

  1. 由于类只会加载一次,则静态变量在内存中也只会存在一份:存在方法区的静态域中

使用static修饰方法:静态方法

  1. 随着类的加载而加载,可以通过"类.静态方法"的方式进行调用

  2. 静态方法中,只能调用静态的方法或属性 非静态方法中,既可以调用非静态的方法或属性,也可以调用静态的方法或属性

注意:在静态的方法内,不能使用this关键字、super关键字

开发中,如何确定一个属性是否要声明为static的?

属性是可以被多个对象所共享的,不会随着对象的不同而不同,此时可以声明为static

开发中,如何确定一个方法是否要声明为static的?

操作静态属性的方法,通常设置为static工具类中的方法,习惯上声明为static的。比如:Math、Arrays、Collections

 

类变量vs实例变量内存解析

 

 

 

final关键字

  1. final可以用来修饰的结构:类、方法、变量

  2. final用来修饰一个类:此类不能被其他类继承 举例:String类、System类、StringBuffer类

  3. final用来修饰方法,表明此方法不可以被重写 举例:Object类中的getClass();

  4. final 用来修饰变量:此时的"变量"就称为一个常量 4.1 final修饰属性:可以考虑赋值的位置有:显式初始化、代码块中初始化、构造器中初始化 4.2 final修饰局部变量: 在使用final修饰形参时,表明此形参是一个常量,当我们调用此方法时,给常量形参赋一个实参。一旦赋值以后 就只能在方法内使用此形参,但不能进行重新赋值 注:static final 用来修饰属性:叫做全局常量

 

abstrate关键字

  1. abstract修饰类:抽象类

    • 此类不能实例化

    • 抽象类中一定有构造器,便于子类实例化时调用(涉及:子类对象实例化的全过程)

    • 开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作

  2. abstract修饰方法:抽象方法

    • 抽象方法只有方法的声明,没有方法体

    • 包含抽象方法的类,一定是一个抽象类。反之,抽象类中可以没有抽象方法

    • 若子类重写了父类中的所有的抽象方法后,此子类可以被实例化 若子类没有重写了父类中的所有的抽象方法,则此子类也是一个抽象类,需要使用abstract修饰

  3. abstract使用上的注意点:

    • abstract不能用来修饰:属性、构造器等结构

    • abstract不能用来修饰私有方法、静态方法、final的方法、final的类

 

interface关键字

  1. 定义接口中的成员

    JDK7.0及以前:只能定义全局常量和抽象方法

    • 全局常量:public static final的,但是书写时,可以省略不写

    • 抽象方法:public abstract的,可以省略不写

    JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法

    • 接口中定义的静态方法,只能通过接口来调用

    • 通过实现类的对象,可以调用接口中的默认方法。 如果实现类重写了接口中的默认方法,调用时,仍然调用的是重写以后的方法

    • 如果子类(或实现类)的父类和实现的接口中声明了同名同参数的默认方法, 那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参数的默认方法。--> 类优先原则

    • 如果实现类实现了多个接口且并没有继承父类,而这多个接口中定义了同名同参数的默认方法。 那么在实现类没有重写此方法的情况下,报错。--> 接口冲突 这就需要我们必须在实现类中重写此方法

    • 在子类(实现类)的方法中调用父类、接口中被重写的方法

      method3();//调用自己定义的重写的方法
      super.method3();//调用的是父类中声明的
      //调用接口中的默认方法
      CompareA.super.method3();
      CompareB.super.method3();
  2. 接口中不能定义构造器,意味着接口不可以实例化

  3. Java开发中,接口通过让类去实现(implements)的方式来使用 如果实现类覆盖了接口中所有的抽象方法,则此实现类就可以被实例化 如果实现类没有覆盖了接口中所有的抽象方法,则此实现类仍为一个抽象类

  4. Java类可以实现多个接口 --> 弥补了Java单继承的局限性 格式:class AA extends BB implements CC,DD{}

  5. 接口与接口之间可以继承,而且可以多继承

 

posted @ 2022-02-04 23:55  阳光真好的博客  阅读(31)  评论(0)    收藏  举报