Java面向对象编程

First Post:

Last Update:

对象

对象的属性和方法

对象都有:

  • 属性
  • 方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 创建类(文件名: Car.java)
public class Car {

// 声明类属性
String make = "Chevrolet";
String model = "Corvette";
int year =2020;
String color = "blue";
double price = 50000.00;

// 声明类方法
void drive() {
System.out.println("You drives the car");
}

void brake() {
System.out.println("You step on the brakes");
}
}

使用类:

1
2
Car myCar = new Car();
myCar.drive();

类的构造函数

作用是为一个类创建不同的实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Human {
String name;
int age;
double weight;

// 类的构造函数
// 用于创建不同的实例
Human(String name, int age, double weight){
this.name = name;
this.age = age;
this.weight = weight;
}

// 访问对象属性
System.out.println(this.name+" is eating");
}
1
Human human = new Human("Rick", 65, 70);

重载构造函数

在一个类里, 有多个名字相同的构造函数, 其区别在于, 其构造函数的传参不同


toString() 方法

一个所有对象都继承的特殊方法
toString 方法返回一个用文本表示对象的字符串

1
2
3
4
public class Car {
String name = 'test';
int year = 2021;
}
1
2
3
4
5
6
7
8
Car car = new Car();

// 打印出来是: Car@36baf30c (内存地址)
system.out.println(car);

// 需要重构toString() 方法
// 如果不重构toString(), 返回的结果与上一个一样
system.out.println(car.toString());

重构 toString() 方法

1
2
3
4
5
6
7
8
public class Car {
String name = 'test';
int year = 2021;

public String toString(){
return name + "\n" + year
}
}

在列表中创建对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Food {
String name;

Food(String name){
this.name = name;
}
}

Food newFood = new Food('pizza')

// 创建对象列表
Food[] test = new Food[3]

// 将对象插入列表
test[0] = newFood;

// 另一种方法
Food[] test = {newFood, ..., ...}

将对象作为传参

汽车类:

1
2
3
4
5
6
7
public class Car{
String name;

Car(String name){
this.name = name;
}
}

停车场类:

1
2
3
4
5
public class Garage{
void park(Car car){
system.out.println("The "+car.name+"is parked in the garage")
}
}

主函数:

1
2
3
4
5
6
// 创建实例
Garage garage = new Garage();
Car car = new Car("BMW");

//传入对象
garage.park(car);

static 关键字

它是一个关键字修饰符
可用于修饰 变量/方法, 其类的对象共享 static 修饰的成员

朋友类:

1
2
3
4
5
6
7
8
9
10
public class Friend{
String name;
// static 修饰符
static int numberOfFriend = 0;

Friend(String name){
this.name = name;
numberOfFriend++;
}
}

主函数:

1
2
3
4
5
6
7
8
// 输出0
system.out.println(Friend.numberOfFriend);

Friend friend1 = new Friend("Tom");
Friend friend2 = new Friend("Jonas");

// 输出2
system.out.println(Friend.numberOfFriend);

static 修饰的成员尽量以 类.成员 进行访问(静态访问)


java 的继承

利用 extends 关键字实现继承
一个类能够获取其他类的属性和方法

载具类:
父类也被称为 super class

1
2
3
4
5
6
7
8
9
10
11
public class Vehicle{
double speed;

void go(){
System.out.println("这辆车在移动");
}

void stop() {
System.out.println("现在刹车");
}
}

继承类 ↓

汽车类:

1
2
3
4
public class Car extends Vehicle{
int wheel = 4;
int doors = 4;
}

自行车类:

1
2
3
4
public class Bicycle extends Vehicle{
int wheel = 2;
int pedals = 2;
}

主函数:

1
2
3
4
5
6
7
Car car = new Car();
Bicycle bicycle = new Bicycle();

// 继承并调用父类方法
car.go();
System.out.println(car.doors);
System.out.println(bicycle.pedals);

java 继承的方法重写

在父类中定义一个方法, 子类可以对其进行重写
以使子类拥有其自己独有的方法

动物类(父类):

1
2
3
4
5
public class Animal{
void speak(){
System.out.println("The animal speak");
}
}

狗类(子类):

1
2
3
4
5
6
7
8
public class Dog extends Animal{
// 子类方法重写
// @Override并非必须, 只是告诉其他人这是方法重写
@Override
void speak(){
System.out.println("The dog goes bark");
}
}

主函数:

1
2
Dog dog = new Dog();
dog.speak();

java 的 super 关键字

类似于 this 关键字
super: 一个引用父类的关键字

人类(父类):

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Person{
String name;
int age;

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

public String toString(){
return this.name + '\n' + this.age;
}
}

super(), 用于继承(使用)父类构造方法
super.方法, 用于继承(使用)父类方法

英雄类(子类):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Hero extends Person{
String power;

// 使用super()方法继承构造函数
Hero(String name, int age, String power){
super(name, age);
this.power = power;
}

public String toString(){
// super关键字调用父类方法
return super.toString() + this.power;
}
}

主函数:

1
2
3
4
5
6
Hero hero1 = new Hero("Batman", 42, "rich");

System.out.println(hero1.name);
System.out.println(hero1.age);
System.out.println(hero1.power);
System.out.println(hero1.toString());

abstract 关键字(抽象类)

抽象类不能被实例化, 但是它们可以拥有一个
没有代码块的子类抽象方法

载具类(父类):

由于载具类过于抽象(载具可以指飞机, 坦克, 船,等等…)
所以可以使用 abstract 关键字(可以提高程序安全性)

1
2
3
4
5
6
public abstract class Vehicle{

// 抽象方法
// 强制用户在子类声明具体方法
abstract void go();
}

汽车类(子类):

1
2
3
4
5
6
7
public class Car extends Vehicle{

@Override
void go(){
System.out.println("司机在开汽车");
}
}

主函数:

1
2
3
Car car = new Car();

car.go();

访问权限关键字

访问权限关键字用于增强程序安全性

  • public
  • protect
  • private

package 是类的集合 , class是代码的集合

关键字 子类 全局
public Y Y Y Y
protected Y Y Y N
Y Y N N
private Y N N N

全局指: 不同的包之间可以进行访问
包指: 可以访问当前的包
子类指: 无论是不同的包还是类; 只要是其子类, 就可以访问
类指: 只能访问本类自身


package1 下的 A.javaB.java

A.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
package package1;
import package2.*;

public class A{
protected String protectMessage = "这是 protected";

public static void main(String[] args){
C c = new C();

// public 全局(如何包)都可以访问
System.out.println(C.publicMessage)
}
}

B.java:

1
2
3
4
5
6
package package1;
import package2.*;

public class B{

}

package2 下的 Asub.javaC.java

Asub.java:
Asub 类是 A 类的子类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package package2;

// 为继承A类的所有内容, 需要用到 import
import package1.*;

public class Asub extends A{
public static void main(String[] args){
C c = new C();
Asub asub = new Asub();

// 默认访问权限: 在同一个包内, 可以访问
System.out.println(C.defaultMessage)

// protected 访问权限, 子类可以访问父类
System.out.println(asub.protectedMessage)
}
}

C.java:

1
2
3
4
5
6
7
8
9
package package2;
import package1.*;

public class C{
public String publicMessage = "这是 public ";
protected String protectedMessage = "这是 protected";
String defaultMessage = "这是默认的访问权限";
private privateMessage = "这是 private";
}

java 的封装

一个可以将类隐藏或转为私有的类属性
封装的类属性只能通过方法 gettersetter 访问

依旧是提高程序安全性, 似乎一般用不到

车类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Car{
private String make;
private String model;
private int year;

Car(String make, String model, int year){
// 为避免代码重复, 当声明了setter方法, 可以在构造函数中调用其setter
this.setMake(make);
this.model = model;
this.year = year;
}

// get方法
public String getMake() {
return make;
}

// set方法
public String setMake(String make){
this.make = make;
}
}

主函数:

1
2
3
4
Car car = new Car("Chevrolet", "Camaro", 2021);

System.out.println(car.getMake());
System.out.println(car.setMake("BMW"));

复制对象

通过再次构造实例化对象, 实现对象复制(内存地址不同)

1
2
3
4
5
6
7
// java 封装的示例代码基础上添加
// 在Car类添加以下代码

public void copy(Car x){
this.setMake(x.getMake())
...
}

java 接口

接口是可以应用于类的模板, 类似于继承
但是接口指定类必须做什么

类只能继承一个父类, 但类可以有多个接口

猎物接口:

1
2
3
4
5
6
public interface Prey{

// 可以在接口中声明方法和属性
// 不同的是, 方法不能指明代码块
void flee();
}

捕食者接口:

1
2
3
public interface Predator{
void hunt();
}

兔子类:

1
2
3
4
5
6
public class Rabbit implements Prey{
// 就行抽象方法一样
void flee(){
System.out.println("兔子在逃跑")
}
}

鹰类:

1
2
3
4
5
public class Hawk implements Predators{
void hunt(){
System.out.println("老鹰在捕猎")
}
}

鱼类:
可以是捕猎者, 也可以是猎物

1
2
3
4
5
6
7
8
9
10
11
public class Fish implements Predator, Prey{
@Override
void hunt() {
System.out.println("大鱼吃小鱼");
}

@Override
void flee() {
System.out.println("小鱼被大鱼吃");
}
}

java 的多态性

多态性指: 识别一个拥有多个类型的对象的能力

载具类(父类):

1
2
3
4
5
public class Vehicle{
public void go(){

}
}

车类:

1
2
3
4
5
6
public class Car extends Vehicle{
@Override
public void go(){
System.out.println("开车!!!")
}
}

自行车类:

1
2
3
4
5
6
public class Bicycle extends Vehicle{
@Override
public void go(){
System.out.println("骑车!!!")
}
}

船类:

1
2
3
4
5
6
public class Boat extends Vehicle{
@Override
public void go(){
System.out.println("开船!!!")
}
}

主函数:

1
2
3
4
5
6
7
8
9
10
11
Car car = new Car();
Bicycle bicycle = new Bicycle();
Boat boat = new Boat();

// 利用多态性, 将对象存入列表
Vehicle[] racers = {car, bicycle, boat};

// 循环调用对象方法
for(Vehicle x : racers) {
x.go();
}

动态的多态性