我有两颗糖

博客小屋

By 某只不愿露脸的尹同学


08-Java面向对象篇

1. 继承

类的继承方法为:

class masterClass{
    private Type arg1;
    private Type arg1;

    public masterClass(Type arg1, Type arg2){
        this.arg1 = arg1;
        this.arg2 = arg2;
    }
}

// 使用关键字 extends 继承
class slaveClass extends masterClass{

    public slaveClass(Type arg1, Type arg2){
        super(arg1, arg2);
    }
}

extends

  • 一个子类只能拥有一个父类, extends 可以继承一个类

superthis 关键字

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

构造器

  • 子类是不继承父类的构造器的,它只是调用(隐式或显式)
  • 如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表;
  • 如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。

1.1 举例

首先看一个具体的例子:

// fileName:Test.java

class Animal{
	private String name;
	private int age;
	public Animal(String name, int age) {
		this.name = name;
		this.age = age;
	}
	public void getInfo() {
		System.out.println("Name: " + this.name);
		System.out.println("Age: " + this.age);
	}
}

class Cat extends Animal{
	public Cat(String name, int age) {
		super(name, age);
//      super.getInfo();
	}
}

public class Test {
	public static void main(String[] args) {
		Cat tom = new Cat("Tom", 3);
		tom.getInfo();
	}
}

上面的代码中定义了3个类:Animal、Cat 和 Test

Animal:父类,定义了动物的基本属性

  • private 属性只有类的方法可以访问和修改
  • public 方法可以被子类继承调用

Cat:子类,继承了 Animal

  • 子类拥有父类非 private 的属性、方法(private 属性不能被继承,因为不能通过 子类的方法来直接访问 private 属性,只能通过调用父类的 public 函数来访问父类的 private 属性)
  • 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展
  • Java 支持单继承和多重继承,不支持多继承

Test:public 类,用来测试

  • Test 类创建了 Cat 的对象,同通过对象调用了父类 Animal 的方法
  • 一个 Java 文件中可以定义多个类
  • 但是最多只有一个类被 public 修饰,并且这个类的类名与文件名必须相同

1.2 关键字

在 Java 中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类;

使用 implements 关键字可以变相的使 Java 具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口;

public interface A {
    public void eat();
    public void sleep();
}

public interface B {
    public void show();
}

public class C implements A,B {
}

final 关键字声明类可以把类定义为不能继承的


2. Override & Overload

2.1 重写 Override

方法重写 是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写;

class Animal{
	private String name;
	private int age;

	public Animal(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public void getInfo() {
		System.out.println("Name: " + this.name);
		System.out.println("Age: " + this.age);
	}
}

class Cat extends Animal{
	private String color;

	public Cat(String name, int age, String color) {
		super(name, age);
		this.color = color;
	}

	public void getInfo() {
		super.getInfo();
		System.out.println("Color: " + this.color);
	}
}

public class Test {
	public static void main(String[] args) {
		Animal ruby = new Animal("Ruby", 2);
		ruby.getInfo();
		Cat tom = new Cat("Tom", 3, "Brown");
		tom.getInfo();
	}
}

上面的代码中,Cat 重载了 Animal的方法 getINfo(),使用 super 关键字调用了父类的方法,输出结果为:

Name: Ruby
Age: 2
Name: Tom
Age: 3
Color: Brown

方法重写规则

  • 返回值和形参都不能改变

  • 访问权限不能比父类中被重写的方法的访问权限更低(即可以降低限制)
  • 声明为 final 或 static 的方法不能被重写
  • 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法

2.2 重载 Overload

方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)

规则

  • 被重载的方法必须改变参数列表(参数个数或类型不一样)
  • 被重载的方法可以改变返回类型
  • 被重载的方法可以改变访问修饰符
  • 被重载的方法可以声明新的或更广的检查异常

方法重写 是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写;

方法重载 是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载;

多态 是同一个行为具有多个不同表现形式或形态的能力,继承、方法的重写重载体现了多态。


3. 封装

  1. 修改属性的可见性来限制对属性的访问,一般限制为private;
  2. 对每个值属性提供对外的公共方法访问,用于对私有属性的访问,它们是外部类访问该类成员变量的入口;
class Animal{

    // 私有属性
	private String kind;
	private String color;

    // 接口
	public Animal(String kind, String color) {
		this.kind = kind;
		this.color = color;
	}
	public void getInfo() {
		System.out.println("kind: " + kind + "\n" + "color: " + color);
	}
}

4. 枚举类型

枚举类型是一个特殊的类,用 enum 来声明

如下定义一个季节的枚举类,在其中枚举类成员:

enum Season{
	SPRING, SUMMER, AUTUMN, WINTER;
	public void getInfo() {
		System.out.println("Four seasons in a year.");
	}
}

下面访问一个枚举类型的所有值:

values() 返回枚举类中所有的值(返回值为数组类型)

enum Season{
	SPRING, SUMMER, AUTUMN, WINTER;
}

public class AbstractClassTest {
	public static void main(String[] args) {

		Season s = Season.AUTUMN;
        System.out.println(s);
		System.out.println(s.getClass());

		for (Season tmp : Season.values()) {
			System.out.print(tmp + " ");
		}
	}
}

5. package

5.1 package 作用

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

5.2 创建和使用包

1. 包的定义

在一个包里面添加类的方法如下:

package 包名;   //多级包用.分开

pulic class Dolphin{

}

注意:

(1) 包名要小写;

(2) 一个源文件只有一个 public 类;

(3) package语句必须在文件中的第一条有效语句

2. 包的目录结构

如图,在当前目录 src 中创建一个类和一个 package , package 包含了两个类 Cat 和 Dog

下面的代码是 Cat 类定义(Dog 类的定义类似)

// src/mypackage/Cat.java
package animals;

public class Cat {
	private String color;
	private String name;

	public Cat(String name, String color) {
		this.color = color;
		this.name = name;
	}

	public void printInfo() {
		System.out.println(name + " is a " + color + " cat.");
	}
}

3. 包的使用

下面是带有主函数的类:

import animals.Cat;
import animals.Dog;

public class PackageTest {

	public static void main(String[] args) {
		Cat tom = new Cat("Tom", "brown");
		tom.printInfo();

		Dog lucy = new Dog("Lucy", "red");
		lucy.printInfo();
	}
}

使用包的时候在源文件最上方声明,也可以一次性包含包内所有的类:

import mypackage.*;

输出的结果为:

Tom is a brown cat.
Lucy is a red dog.

5.3 编译运行

// 单独一个文件时
javac A.java

// 包含包时(*.java代表当前目录下的所有源文件)
javac -d . *.java
-->