Java的继承

继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
通过继承的语法可以减少代码量

生活中的继承:

Java 的 继承,重写,重载,多态,封装,接口,包,抽象类 - 图1

  1. // 公共父类
  2. public class Animal {
  3. private String name;
  4. private int id;
  5. public Animal(String myName, int myid) {
  6. name = myName;
  7. id = myid;
  8. }
  9. public void eat(){
  10. System.out.println(name+"正在吃");
  11. }
  12. public void sleep(){
  13. System.out.println(name+"正在睡");
  14. }
  15. public void introduction() {
  16. System.out.println("大家好!我是" + id + "号" + name + ".");
  17. }
  18. }
  19. // 企鹅类
  20. public class Penguin extends Animal {
  21. public Penguin(String myName, int myid) {
  22. super(myName, myid);
  23. }
  24. }
  25. // 老鼠类
  26. public class Mouse extends Animal {
  27. public Mouse(String myName, int myid) {
  28. super(myName, myid);
  29. }
  30. }

image.png

extends 与 implements 关键字

implements实现接口,达到多继承的目的
接口主要是为了规范,规定一种一致的实现,或一种数据传递的方式,依赖接口,而不要依赖于实现

  1. public class Animal {
  2. private String name;
  3. private int id;
  4. public Animal(String myName, String myid) {
  5. //初始化属性值
  6. }
  7. public void eat() { //吃东西方法的具体实现 }
  8. public void sleep() { //睡觉方法的具体实现 }
  9. }
  10. public class Penguin extends Animal{
  11. }
  12. // implements实现接口,达到多继承的目的
  13. public interface A {
  14. public void eat();
  15. public void sleep();
  16. }
  17. public interface B {
  18. public void show();
  19. }
  20. public class C implements A,B {
  21. }

super 与 this 关键字

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

final关键字

final 关键字声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写:

重写与重载

重写(Override)

重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!

重载(Overload)

重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
最常用的地方就是构造器的重载。
重载规则:

  • 被重载的方法必须改变参数列表(参数个数或类型不一样);
  • 被重载的方法可以改变返回类型;
  • 被重载的方法可以改变访问修饰符;
  • 被重载的方法可以声明新的或更广的检查异常;
  • 方法能够在同一个类中或者在一个子类中被重载。
  • 无法以返回值类型作为重载函数的区分标准。

image.png

多态

多态是同一个行为具有多个不同表现形式或形态的能力。
多态就是同一个接口,使用不同的实例而执行不同操作,如图所示:
image.png

多态的优点

    1. 消除类型之间的耦合关系
    1. 可替换性
    1. 可扩充性
    1. 接口性
    1. 灵活性
    1. 简化性

      多态存在的三个必要条件

  • 继承

  • 重写
  • 父类引用指向子类对象
  1. public class Test {
  2. public static void main(String[] args) {
  3. show(new Cat()); // 以 Cat 对象调用 show 方法
  4. show(new Dog()); // 以 Dog 对象调用 show 方法
  5. Animal a = new Cat(); // 向上转型
  6. a.eat(); // 调用的是 Cat 的 eat
  7. Cat c = (Cat)a; // 向下转型
  8. c.work(); // 调用的是 Cat 的 work
  9. }
  10. public static void show(Animal a) {
  11. a.eat();
  12. // 类型判断
  13. if (a instanceof Cat) { // 猫做的事情
  14. Cat c = (Cat)a;
  15. c.work();
  16. } else if (a instanceof Dog) { // 狗做的事情
  17. Dog c = (Dog)a;
  18. c.work();
  19. }
  20. }
  21. }
  22. abstract class Animal {
  23. abstract void eat();
  24. }
  25. class Cat extends Animal {
  26. public void eat() {
  27. System.out.println("吃鱼");
  28. }
  29. public void work() {
  30. System.out.println("抓老鼠");
  31. }
  32. }
  33. class Dog extends Animal {
  34. public void eat() {
  35. System.out.println("吃骨头");
  36. }
  37. public void work() {
  38. System.out.println("看家");
  39. }
  40. }

抽象类

在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。
父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。
在Java中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。

  1. /* 文件名 : Employee.java */
  2. public abstract class Employee
  3. {
  4. private String name;
  5. private String address;
  6. private int number;
  7. public Employee(String name, String address, int number)
  8. {
  9. System.out.println("Constructing an Employee");
  10. this.name = name;
  11. this.address = address;
  12. this.number = number;
  13. }
  14. public double computePay()
  15. {
  16. System.out.println("Inside Employee computePay");
  17. return 0.0;
  18. }
  19. public void mailCheck()
  20. {
  21. System.out.println("Mailing a check to " + this.name
  22. + " " + this.address);
  23. }
  24. public String toString()
  25. {
  26. return name + " " + address + " " + number;
  27. }
  28. public String getName()
  29. {
  30. return name;
  31. }
  32. public String getAddress()
  33. {
  34. return address;
  35. }
  36. public void setAddress(String newAddress)
  37. {
  38. address = newAddress;
  39. }
  40. public int getNumber()
  41. {
  42. return number;
  43. }
  44. }

抽象方法

如果你想设计这样一个类,该类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法。
Abstract 关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体。
抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。

  1. public abstract class Employee
  2. {
  3. private String name;
  4. private String address;
  5. private int number;
  6. public abstract double computePay();
  7. //其余代码
  8. }

抽象类总结规定

    1. 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
    1. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
    1. 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
    1. 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
    1. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。

封装

在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部份包装、隐藏起来的方法。
封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。
要访问该类的代码和数据,必须通过严格的接口控制。
封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。
适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。

封装的优点

    1. 良好的封装能够减少耦合。
    1. 类内部的结构可以自由修改。
    1. 可以对成员变量进行更精确的控制。
    1. 隐藏信息,实现细节。

      实现Java封装的步骤

  1. // 修改属性的可见性来限制对属性的访问(一般限制为private),例如:
  2. public class Person {
  3. private String name;
  4. private int age;
  5. }

接口

接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。
接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。

接口与类相似点:

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

    接口与类的区别:

  • 接口不能用于实例化对象。

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

    接口特性

  • 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。

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

    抽象类和接口的区别

    1. 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
    1. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
    1. 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
    1. 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
  1. [可见度] interface 接口名称 [extends 其他的接口名] {
  2. // 声明变量
  3. // 抽象方法
  4. }
  5. // 文件名: Sports.java
  6. public interface Sports
  7. {
  8. public void setHomeTeam(String name);
  9. public void setVisitingTeam(String name);
  10. }
  11. // 文件名: Football.java
  12. public interface Football extends Sports
  13. {
  14. public void homeTeamScored(int points);
  15. public void visitingTeamScored(int points);
  16. public void endOfQuarter(int quarter);
  17. }
  18. // 文件名: Hockey.java
  19. public interface Hockey extends Sports
  20. {
  21. public void homeGoalScored();
  22. public void visitingGoalScored();
  23. public void endOfPeriod(int period);
  24. public void overtimePeriod(int ot);
  25. }
  26. public class XXX implements Football{
  27. // ...
  28. }
  29. public class XXX implements Hockey{
  30. // ...
  31. }

包 package

为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间。

包的作用

  • 1、把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。
  • 2、如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
  • 3、包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。

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

  1. package pkg1[.pkg2[.pkg3…]];
  2. package net.java.util;
  3. public class Something{
  4. ...
  5. }

那么它的路径应该是 net/java/util/Something.java 这样保存的。 package(包) 的作用是把不同的 java 程序分类保存,更方便的被其他 java 程序调用。
一个包(package)可以定义为一组相互联系的类型(类、接口、枚举和注释),为这些类型提供访问保护和命名空间管理的功能。
以下是一些 Java 中的包:

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

开发者可以自己把一组类和接口等打包,并定义自己的包。而且在实际开发中这样做是值得提倡的,当你自己完成类的实现之后,将相关的类分组,可以让其他的编程者更容易地确定哪些类、接口、枚举和注释等是相关的。
由于包创建了新的命名空间(namespace),所以不会跟其他包中的任何名字产生命名冲突。使用包这种机制,更容易实现访问控制,并且让定位相关类更加简单。

设置 CLASSPATH 系统变量

用下面的命令显示当前的CLASSPATH变量:

  • Windows 平台(DOS 命令行下):C:> set CLASSPATH
  • UNIX 平台(Bourne shell 下):# echo $CLASSPATH

删除当前CLASSPATH变量内容:

  • Windows 平台(DOS 命令行下):C:> set CLASSPATH=
  • UNIX 平台(Bourne shell 下):# unset CLASSPATH; export CLASSPATH

设置CLASSPATH变量:

  • Windows 平台(DOS 命令行下): C:> set CLASSPATH=C:\users\jack\java\classes
  • UNIX 平台(Bourne shell 下):# CLASSPATH=/home/jack/java/classes; export CLASSPATH