所在位置:首页 → 编程语言 → Java → Java基础七:面向对象

Java基础七:面向对象

发布: 更新时间:2022-10-17 22:30:07

继承

1.继承类型

需要注意的是 Java 不支持多继承,但支持多重继承。

java继承类型

2.继承关键字

extends:类的继承是单一继承

implements:接口的继承,可继承多个接口

3.super 与 this 关键字

super:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。

this:指向自己的引用。

4.final 关键字

final 可以用来修饰变量(包括类属性、对象属性、局部变量和形参)、方法(包括类方法和对象方法)和类。

使用final修饰类,不能被继承。修饰方法,不能被重写。

5.构造器

子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。

自动调用父类的无参构造器,父类的有参构造器使用super调用

override/overload

1.方法的重写规则

  • 参数列表与被重写方法的参数列表必须完全相同
  • 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同)。
  • 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。
  • 父类的成员方法只能被它的子类重写。
  • 声明为 final 的方法不能被重写。
  • 声明为 static 的方法不能被重写,但是能够被再次声明。
  • 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。
  • 子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。
  • 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
  • 构造方法不能被重写。
  • 如果不能继承一个类,则不能重写该类的方法。

2.Super 关键字

调用父类的方法

3.重载的规则:

  • 被重载的方法必须改变参数列表(参数个数或类型不一样);
  • 被重载的方法可以改变返回类型;
  • 被重载的方法可以改变访问修饰符;
  • 被重载的方法可以声明新的或更广的检查异常;
  • 方法能够在同一个类中或者在一个子类中被重载(子类中写了一个跟父类同名但是类型和参数都不同的方法,对于父类来说相当于重载父类方法了)。
  • 无法以返回值类型作为重载函数的区分标准。

多态

1.多态存在的三个必要条件

  • 继承
  • 重写
  • 父类引用指向子类对象:Parent p = new Child();

2.多态的实现方式

方式一:重写

方式二:接口

  • 1. 生活中的接口最具代表性的就是插座,例如一个三接头的插头都能接在三孔插座中,因为这个是每个国家都有各自规定的接口规则,有可能到国外就不行,那是因为国外自己定义的接口类型。
  • 2. java中的接口类似于生活中的接口,就是一些方法特征的集合,但没有方法的实现。

方式三:抽象类和抽象方法

抽象类

用abstract修饰符修饰

  • 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
  • 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
  • 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
  • 构造方法,类方法(用 static、final修饰的方法)不能声明为抽象方法。
  • 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
public abstract class Employee   # 抽象类里可以有正常实现的普通方法
{
   private String name;
   private String address;
   private int number;
   
   public abstract double computePay();  # 抽象方法,在继承的子类中实现
   
   //其余代码
}

封装

实现Java封装的步骤

修改属性的可见性来限制对属性的访问(一般限制为private),例如:

public class Person {
    private String name;
    private int age;
}

这段代码中,将 name 和 age 属性设置为私有的,只能本类才能访问,其他类都访问不了,如此就对信息进行了隐藏。

2. 对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问,例如:

public class Person{
    private String name;
    private int age;
​
    public int getAge(){
      return age;
    }
​
    public String getName(){
      return name;
    }
​
    public void setAge(int age){
      this.age = age;  # 采用 this 关键字是为了解决实例变量(private String name)
    }                  # 和局部变量(setName(String name)中的name变量)之间发生的同名的冲突。
​
    public void setName(String name){
      this.name = name;
    }
}

接口

接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。

1.接口的语法

[可见度] interface 接口名称 [extends 其他的接口名] {   # 接口是隐式抽象的,默认abstract。
        // 声明变量                                 # 隐式指定:public static final 
        // 抽象方法                                 # 方法也是隐式抽象的,默认public abstract
}

实例:

/* 文件名 : Animal.java */
interface Animal {
   public void eat();
   public void travel();
}

2.接口的实现

/* 文件名 : MammalInt.java */
public class MammalInt implements Animal{
   # 用implements关键字来继承接口,如果实现接口的类是抽象类,那么就没必要实现该接口的方法。   
   # 类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型。
   # 类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。
   public void eat(){
      System.out.println("Mammal eats");
   }
 
   public void travel(){
      System.out.println("Mammal travels");
   } 
 
   public int noOfLegs(){
      return 0;
   }
 
   public static void main(String args[]){
      MammalInt m = new MammalInt();
      m.eat();
      m.travel();
   }
}

3.接口的继承

接口之间的继承支持多继承,使用extends

public interface Hockey extends Sports, Event

4.标记接口

标记接口是没有任何方法和属性的接口.它仅仅表明它的类属于一个特定的类型,供其他代码来测试允许做一些事情。没有任何方法的接口被称为标记接口。

package java.util;
public interface EventListener
{}

标记接口主要用于以下两种目的:

  • 建立一个公共的父接口:正如EventListener接口,这是由几十个其他接口扩展的Java API,你可以使用一个标记接口来建立一组接口的父接口。例如:当一个接口继承了EventListener接口,Java虚拟机(JVM)就知道该接口将要被用于一个事件的代理方案。
  • 向一个类添加数据类型:这种情况是标记接口最初的目的,实现标记接口的类不需要定义任何接口方法(因为标记接口根本就没有方法),但是该类通过多态性变成一个接口类型。

枚举

Java 枚举是一个特殊的类一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等。

public class Test
{
    enum Color
    {
        RED, GREEN, BLUE;     #  可以定义在类里面
    }
 
    // 执行输出结果
    public static void main(String[] args)
    {
        Color c1 = Color.RED;  # 获取枚举类型的属性
        # for (Color myVar : Color.values()) {  可以使用for语句迭代enum里面的属性
        # System.out.println(myVar);}
        System.out.println(c1);
    }
}

1.枚举类常用方法

  • values() 返回枚举类中所有的值。
  • ordinal()方法可以找到每个枚举常量的索引,就像数组索引一样。
  • valueOf()方法返回指定字符串值的枚举常量。

2.枚举类成员

枚举跟普通类一样可以用自己的变量、方法和构造函数,构造函数只能使用 private 访问修饰符,所以外部无法调用。

枚举既可以包含具体方法,也可以包含抽象方法。 如果枚举类具有抽象方法,则枚举类的每个实例都必须实现它。

enum Color
{
    RED, GREEN, BLUE;
 
    // 构造函数
    private Color()
    {
        System.out.println("Constructor called for : " + this.toString());
    }
 
    public void colorInfo()
    {
        System.out.println("Universal Color");
    }
}
 
public class Test
{    
    // 输出
    public static void main(String[] args)
    {
        Color c1 = Color.RED;
        System.out.println(c1);
        c1.colorInfo();
    }
}

Java 使用包(package)这种机制是为了防止命名冲突,访问控制,提供搜索和定位类(class)、接口、枚举(enumerations)和注释(annotation)等。

包语句的语法格式为:

package pkg1[.pkg2[.pkg3…]];

例如,一个Something.java 文件它的内容

package net.java.util;
public class Something{
   ...
}

一个包(package)可以定义为一组相互联系的类型(类、接口、枚举和注释),为这些类型提供访问保护和命名空间管理的功能。

以下是一些 Java 中的包:

  • java.lang-打包基础的类
  • java.io-包含输入输出功能的函数

包声明应该在源文件的第一行,每个源文件只能有一个包声明,这个文件中的每个类型都应用于它。

如果一个源文件中没有使用包声明,那么其中的类,函数,枚举,注释等将被放在一个无名的包(unnamed package)中。

1.创建包

2.import 关键字

import package1[.package2…].(classname|*);

3.包的目录结构

类放在包中会有两种主要的结果:

  • 包名成为类名的一部分,正如我们前面讨论的一样。
  • 包名必须与相应的字节码所在的目录结构相吻合。
标签:, , , , , , , , , ,
文章排行