java类 面向对象

2018/02/01 Java 共 3511 字,约 11 分钟

访问权限

四种访问权限控制

Java 中一共有四种访问权限控制,其权限控制的大小情况是这样的:public > protected > default(包访问权限) > private ,具体的权限控制看下面表格,列所指定的类是否有权限允许访问行的权限控制下的内容:

访问权限本类本包的类非本包的子类非本包的非子类
public是是是是
protected是是是否
default是是否否
private是否否否

可以对类或类中的成员(字段和方法)加上访问修饰符。

  • 类可见表示其它类可以用这个类创建实例对象。
  • 成员可见表示其它类可以用这个类的实例对象访问到该成员;

protected 用于修饰成员,表示在继承体系中成员对于子类可见,但是这个访问修饰符对于类没有意义。

没有写修饰符时,默认权限是:仅限同一个包内可访问。适用于内部组件之间的协作但不对外暴露。

构造器的访问权限

构造器的访问权限可以是以上四种权限中的任意一种:

1、采用 private:一般是不允许直接构造这个类的对象,再结合工厂方法(static方法),实现单例模式。注意:所有子类都不能继承它。 2、采用包访问控制:比较少用,这个类的对象只能在本包中使用,但是如果这个类有static 成员,那么这个类还是可以在外包使用;(也许可以用于该类的外包单例模式)。 注意:外包的类不能继承这个类; 3、采用 protected :就是为了能让所有子类继承这个类,但是外包的非子类不能访问这个类; 4、采用 public :对于内外包的所有类都是可访问的;

注意: 构造方法有点特殊,因为子类的构造器初始化时,都要调用父类的构造器,所以一旦父类构造器不能被访问,那么子类的构造器调用失败,意味子类继承父类失败!

继承

继承

//类继承
class a{

}
class b extends a{

}
//接口定义和实现
interface a{

}
class b implements a{

}

继承中函数执行优先级

继承链中优先级为:

this.show(O), super.show(O), this.show((super)O), super.show((super)O)

O是对象,(super)O是向上转型。

即 先调用方向上转型,再参数向上转型。

构造器

  • 子类不能继承父类的构造器(构造方法或者构造函数),但是父类的构造器带有参数的,则必须在子类的构造器中显式地通过super关键字调用父类的构造器并配以适当的参数列表。
  • 如果父类有无参构造器,则在子类的构造器中用super调用父类构造器不是必须的,如果没有使用super关键字,系统会自动调用父类的无参构造器。
  • super()等函数要在子类构造器的第一行

重写

  • 存在于继承体系中,指子类实现了一个与父类在方法声明上完全相同的一个方法。

    为了满足里式替换原则,重写有以下三个限制:

    • 子类方法的访问权限必须大于等于父类方法;
    • 子类方法的返回类型必须是父类方法返回类型或为其子类型。
    • 子类方法抛出的异常类型必须是父类抛出异常类型或为其子类型。

    使用 @Override 注解,可以让编译器帮忙检查是否满足上面的三个限制条件。

  • 变量不能被重写(覆盖),”重写”的概念只针对方法,如果在子类中”重写”了父类中的变量,那么在编译时会报错。

重载

  • 被重载的方法可以改变访问修饰符

抽象类

抽象类和抽象方法都使用 abstract 关键字进行声明。如果一个类中包含抽象方法,那么这个类必须声明为抽象类。

抽象类和普通类最大的区别是,抽象类不能被实例化,只能被继承。

public abstract class AbstractClassExample {

    protected int x;
    private int y;

    public abstract void func1();

    public void func2() {
        System.out.println("func2");
    }
}
public class AbstractExtendClassExample extends AbstractClassExample {
    @Override
    public void func1() {
        System.out.println("func1");
    }
}
// AbstractClassExample ac1 = new AbstractClassExample(); // 'AbstractClassExample' is abstract; cannot be instantiated
AbstractClassExample ac2 = new AbstractExtendClassExample();
ac2.func1();
  1. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
  2. 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
  3. 构造方法,类方法(用static修饰的方法)不能声明为抽象方法。
  4. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。

接口

接口是抽象类的延伸,在 Java 8 之前,它可以看成是一个完全抽象的类,也就是说它不能有任何的方法实现。

从 Java 8 开始,接口也可以拥有默认的方法实现,这是因为不支持默认方法的接口的维护成本太高了。在 Java 8 之前,如果一个接口想要添加新的方法,那么要修改所有实现了该接口的类,让它们都实现新增的方法。

接口的成员(字段 + 方法)默认都是 public 的,并且不允许定义为 private 或者 protected。从 Java 9 开始,允许将方法定义为 private,这样就能定义某些复用的代码又不会把方法暴露出去。

接口的字段默认都是 static 和 final 的。

public interface InterfaceExample {

    void func1();

    default void func2(){
        System.out.println("func2");
    }

    int x = 123;
    // int y;               // Variable 'y' might not have been initialized
    public int z = 0;       // Modifier 'public' is redundant for interface fields
    // private int k = 0;   // Modifier 'private' not allowed here
    // protected int l = 0; // Modifier 'protected' not allowed here
    // private void fun3(); // Modifier 'private' not allowed here
}
public class InterfaceImplementExample implements InterfaceExample {
    @Override
    public void func1() {
        System.out.println("func1");
    }
}
// InterfaceExample ie1 = new InterfaceExample(); // 'InterfaceExample' is abstract; cannot be instantiated
InterfaceExample ie2 = new InterfaceImplementExample();
ie2.func1();
System.out.println(InterfaceExample.x);

接口与类相似点:

  • 一个接口可以有多个方法。
  • 接口文件保存在 .java 结尾的文件中,文件名使用接口名。
  • 接口的字节码文件保存在 .class 结尾的文件中。
  • 接口相应的字节码文件必须在与包名称相匹配的目录结构中。

接口与类的区别:

  • 接口不能用于实例化对象。
  • 接口没有构造方法。
  • 接口中所有的方法必须是抽象方法。
  • 接口不能包含成员变量,除了 static 和 final 变量。
  • 接口不是被类继承了,而是要被类实现。
  • 接口支持多继承。

接口特性

  • 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。
  • 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。
  • 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。

抽象类和接口的区别

  1. 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
  2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
  3. 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
  4. 一个类只能继承一个抽象类,而一个类却可以实现多个接口。

Search

    Table of Contents