面向对象编程(OOP,Object-Oriented Programming)

茴香豆 Lv5

首先思考解决问题需要那些分类,然后对这些分类进行单独思考,最后对分类下的细节进行面向过程思索。

以类的方式组织代码,以对象的组织(封装)数据。

三大特性:封装,继承,多态

方法的定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.oop;

// Demo01 类
public class Demo01 {
// main 方法
public static void main(String[] args) {

}

/**
* 修饰符 返回值类型 方法名(...){
* // 方法体
* return 返回值
* }
*/
public String sayHello(){
return "Hello, World";
}
public int max(int a, int b){
return a > b ? a : b;
}
}

方法调用

1
2
3
4
5
6
7
8
9
10
11
12
package com.oop;
// 学生类
public class Student {
// 非静态方法,需要先实例化,再调用
public void say(){
System.out.println("学生说话了");
}
// 静态方法,不需要实例化, 直接调用
static public void sayHello(){
System.out.println("Hello");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.oop;
// 引用传递:对象,本质还是值传递
public class Demo03 {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name);
Demo03.change(person);
System.out.println(person.name);
}

public static void change(Person person){
// person是一个对象:指向的 ---> Person person = new Person(); 这是一个具体的人,可以改变属性!
person.name = "HUI";
}
}

class Person{
String name; // null;
}

引用传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.oop;
// 引用传递:对象,本质还是值传递
public class Demo03 {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name);
Demo03.change(person);
System.out.println(person.name);
}

public static void change(Person person){
// person是一个对象:指向的 ---> Person person = new Person(); 这是一个具体的人,可以改变属性!
person.name = "HUI";
}
}

class Person{
String name; // null;
}

类和对象的创建

1
2
3
4
5
6
7
8
9
10
11
12
package com.oop.demo04;
// 学生类
public class Student {
// 属性:字段
String name; // null
int age; // 0

// 方法
public void studt(){
System.out.println("学习");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.oop.demo04;
import com.oop.demo04.Student;

// 一个项目应该只存在一个main方法
public class Application {
public static void main(String[] args) {
// 类:抽象的,实例化
// 类实例化后会返回一个具体的对象
Student xiaoming = new Student();
Student xiaohong = new Student();

xiaoming.name = "小明";
xiaoming.age = 3;

System.out.println(xiaoming.name);
System.out.println(xiaoming.age);

xiaohong.name = "小红";
xiaohong.age = 6;

System.out.println(xiaohong.name);
System.out.println(xiaohong.age);
}
}

构造器详解(必须掌握)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.oop.demo04;

public class Person {
// 一个类即使什么都不写,也会存在一个构造器(构造方法)
// 构造器:1. 和类名相同 2. 没有返回值
// 显式定义构造器

String name;
// 实例化初始值
// 1. 使用new关键字,本质是在调用构造器
// 2. 构造器用来初始化值
public Person(){
this.name = "HUI";
}

// 有参构造:一旦定义了有参构造,无参构造就必须显示定义
public Person(String name){
this.name = name;
}

// alt + insert 生成构造器
}

封装

程序设计要求”高内聚,低耦合“。

  • 高内聚:即使类的内部数据操作细节自己完成,不允许外部干涉。
  • 低耦合:仅暴漏少量的方法给外部使用。

属性私有,get / set

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.oop.demo05;
/**
* 1. 提高程序安全性,保护数据
* 2. 隐藏代码的实现细节
* 3. 统一接口
* 4. 增加系统可维护性
*/
public class Student {
// 属性私有
private String name;
private int id;
private char sex;
private int age;
// 提供一些可以操作这个属性的方法
// 提供一些 public 的 get、set 方法
// get 获得数据值
public String getName(){
return this.name;
}
// set 设置数据值
public void setName(String name){
this.name = name;
}

// alt + insert 自动生成 get set 方法

public int getAge() {
return age;
}

public void setAge(int age) {
if (age <= 120 && age > 0){
this.age = age;
} else {
this.age = 3;
}

}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.oop.demo05;

public class Application {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("HUI");
System.out.println(s1.getName()); // HUI
s1.setAge(70);
System.out.println(s1.getAge()); // 70
s1.setAge(-1);
System.out.println(s1.getAge()); // 3
}
}

继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.oop.demo06;
// Java中,所有的类,都默认直接或者间接继承Object类
// Java中类只有单继承,没有多继承!一个儿子只能有一个爸爸,但是一个爸爸可以有多个儿子
// 父类
public class Person {
/** 优先级列表
* public
* protected
* default
* private
*/
private int money = 100_000_000;

public void say(){
System.out.println("说话");
}

public int getMoney() {
return money;
}

public void setMoney(int money) {
this.money = money;
}
}
1
2
3
4
5
package com.oop.demo06;
// 派生类/子类
public class Student extends Person{
// ctrl + h
}
1
2
3
4
package com.oop.demo06;
// 派生类/子类
public class Teacher extends Person{
}
1
2
3
4
5
6
7
8
9
package com.oop.demo06;

public class Application {
public static void main(String[] args) {
Student student = new Student();
student.say(); // 说话
System.out.println(student.getMoney());
}
}

super - this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.oop.demo06;
// 父类
public class Person {
public Person() {
// 隐藏代码,默认调用了父类的无参构造
super(); // 调用父类构造器,必须要在子类构造器的第一行,该行可不写,默认调用
System.out.println("Person 无参执行了");
}

protected String name = "HUI";

public void print(){
System.out.println("Person");
}
// 私有的 函数/变量 无法被继承
private void print1(){
System.out.println("private");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.oop.demo06;
// 派生类/子类

/** super注意点
* 1. super调用弗雷的构造方法,必须在构造方法的第一个
* 2. super必须只能出现在子类的方法或者构造方法中
* 3. super 和 this 不能同时调用构造方法
* 4. this(); 本类构造,super(); 父类构造
*/
public class Student extends Person{
public Student() {
System.out.println("Student无参执行了");
}

private String name = "Tong";

public void test(String name){
System.out.println(name); // FENG
System.out.println(this.name); // Tong
System.out.println(super.name); // HUI
}

public void print(){
System.out.println("Student");
}

public void test1(){
print(); // Student
this.print(); // Student
super.print(); // Person
}
}
1
2
3
4
5
6
7
8
9
package com.oop.demo06;

public class Application {
public static void main(String[] args) {
Student student = new Student();
student.test("FENG");
student.test1();
}
}

方法重写(重点)–> 多态

1
2
3
4
5
6
7
package com.oop.demo07;

public class B {
public void test(){
System.out.println("B=>test()");
}
}
1
2
3
4
5
6
7
8
9
package com.oop.demo07;

public class A extends B{
// Override 重写
@Override // 注解:有功能的注解
public void test() {
System.out.println("A=>test()");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.oop.demo07;

/** 重写:需要有继承关系,子类重写父类方法
* 1. 方法名必须相同
* 2. 参数列表必须相同
* 3. 修饰符:范围可以扩大但是不能缩小 public > protected > default > private
* 4. 抛出的异常:范围,可以被缩小,但不能扩大 ClassNotFoundException --> Exception(大)
*
* 重写,子类的方法与父类必须一直,方法体不同
* 为什么重写:
* 1. 父类的功能,子类不一定需要,或者不一定满足
* 2. alt + insert --> overrise;
*/
public class Application {
// 静态方法和非静态方法区别很大!
// 静态方法:
// 非静态:重写
public static void main(String[] args) {
// 方法的调用只和左边,定义的类型有关
A a = new A();
a.test(); // A=>test()
// 父类的引用指向了子类
B b = new A(); // 子类重写了父类的方法
b.test(); // A=>test()
}
}

多态

动态编译:类型:可扩展

1
2
3
4
5
6
7
package com.oop.demo08;

public class Person {
public void run(){
System.out.println("run");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
package com.oop.demo08;

public class Student extends Person{
@Override
public void run() {
System.out.println("son");
}

public void eat(){
System.out.println("eat");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.oop.demo08;

/** 多态
* 1. 多态是方法的多态,属性没有多态
* 2. 父类和子类,有联系,否则出现类型转换异常 ClassCastException
* 3. 存在条件:继承关系,方法需要重写,父类的引用指向子类对象 Father father -> new Son();
* 1. static 方法,属于类,它不属于实力
* 2. final 常量
* 3. private 私有
*/
public class Application {
public static void main(String[] args) {
// 一个对象的实际类型是确定的
// new Student();
// new Person();

// 可以指向的引用类型就不确定了:父类的引用指向子类

// 子类 能调用的方法都是自己的,或者继承父类的
Student s1 = new Student();
// 父类,可以指向子类,但是不能调用子类独有的方法
Person s2 = new Student();
Object s3 = new Student();

// 对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
s2.run(); // 1. run 2. son 子类重写父类的方法,执行子类的方法
s1.run(); // son

// s2.eat(); 报错
s1.eat();
}
}

instanceof 和 类型转换

instanceof 判断两个类之间是否是父子关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class Application {
public static void main(String[] args) {

// Object > String
// Object > Person > Student
// Object > Person > Teacher
Object object = new Student();

System.out.println(object instanceof Student); // true
System.out.println(object instanceof Person); // true
System.out.println(object instanceof Object); // true
System.out.println(object instanceof Teacher); // false
System.out.println(object instanceof String); // false
System.out.println("====================");
Person person = new Student();
System.out.println(person instanceof Student); // true
System.out.println(person instanceof Person); // true
System.out.println(person instanceof Object); // true
System.out.println(person instanceof Teacher); // false
// System.out.println(person instanceof String); // false
System.out.println("====================");
Student student = new Student();
System.out.println(student instanceof Student); // true
System.out.println(student instanceof Person); // true
System.out.println(student instanceof Object); // true
// System.out.println(student instanceof Teacher); // false
// System.out.println(person instanceof String); // false
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.oop.demo08;
/**
* 1. 父类引用指向子类的对象
* 2. 把子类转换为父类,向上转型;
* 3. 把父类转换为子类,向下转型;强制转换
* 4. 方便方法的调用,减少重复的代码!简介
*
* 抽象: 封装、继承、多态! 抽象类,接口
*/
public class Application {
public static void main(String[] args) {
// 类型之间的转化: 基本类型转换 高低 64 32 16 8
// 类型之间的转化: 父 子
// 高 低
Person obj = new Student();
// student 将这个对象转换为 Student 类型, 我们就可以使用 Student 类型的方法了!

Student student = (Student) obj;
student.go();
// 子类转换为父类,可能丢失自己的本来的一些方法!
}
}

static关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.oop.demo09;

public class Person {
/**
* 输出:
* 静态代码块
* 匿名代码块
* 构造方法
* ====================
* 匿名代码块
* 构造方法
*/
// 2: 赋初值~
{
// 代码块(匿名代码块)
System.out.println("匿名代码块");
}
// 1:只执行一次~
static {
// 静态代码块
System.out.println("静态代码块");
}
// 3
public Person(){
System.out.println("构造方法");
}

public static void main(String[] args) {
Person person1 = new Person();
System.out.println("====================");
Person person2 = new Person();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.oop.demo09;

public class Student {
private static int age; // 静态变量 多线程!
private double score; // 非静态变量

public void run(){}

public static void go(){}

public static void main(String[] args) {
Student s1 = new Student();
System.out.println(Student.age);
// System.out.println(Student.score); // 报错
System.out.println(s1.age);
System.out.println(s1.score);

go();
// run(); // 报错
}
}
1
2
3
4
5
6
7
8
9
10
11
12
package com.oop.demo09;

// 静态导入包~
import static java.lang.Math.random;
import static java.lang.Math.PI;

public class Test {
public static void main(String[] args) {
System.out.println(random());
System.out.println(PI);
}
}

抽象类

abstract 修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。

1
2
3
4
5
package com.oop.demo10;

// 抽象类的所有方法,继承了它的子类,都必须要实现它的方法~ 除非~
public class A {
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.oop.demo10;
// abstract 抽象类: 类 extends: 单继承~ (接口可以多继承)插座~ (接口可以多继承)
public abstract class Action {
// 约束~有人帮我们实现~
// abstract, 抽象方法, 只有方法名字, 没有方法的实现
public abstract void doSomething();

// 1. 不能 new 这个抽象类, 只能靠子类去实现它;约束!
// 2. 抽象类中可以写普通的方法~
// 3. 抽象方法必须在抽象类中~
// 抽象的抽象:约束~

// 思考题? new, 存在构造器么?
//存在的意义 抽象出来~ 提高开发效率
}
1
2
3
4
5
6
7
package com.oop.demo10;

public class Application {
public static void main(String[] args) {
// new Action(); // 'Action' 为 abstract;无法实例化
}
}

接口的定义与实现

  • 普通类:只有具体的实现
  • 抽象类:具体实现和规范(抽象方法)都有!
  • 接口:只有规划!自己无法写方法专业的约束!约束的实现分离:面向接口编程

OO的精髓,是对对象的抽象,最能体现这一点的就是接口。

声明类的关键字是class,声明接口的关键字是interface

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.oop.demo11;
// 抽象的思维是很重要的
// interface 定义的关键字, 接口都需要有实现类
public interface UserService {
/**
* 作用
* 1. 约束
* 2. 定义一些方法,让不同的人实现
* 3. 方法默认 public abstract
* 4. 变量默认 public static final
* 5. 接口不能被实例化~,接口中没有构造方法
* 6. implements 可以实现多个接口
* 7. 必须要重写接口中的方法
*/
// 都是常量~ public static final
int AGE = 99; // 一般不在接口里定义常量

// 接口中的所有定义的方法其实都是抽象的 public abstract
// public abstract void run();
void run(); // 默认 public abstract
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
1
2
3
4
5
package com.oop.demo11;

public interface TimeService {
void timer();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.oop.demo11;

// 抽象类:extends~
// 类 可以实现接口 implements 接口
// 实现接口的类,就需要重写接口中的方法~

// 多继承~利用接口实现多继承~
public class UserServiceImpl implements UserService, TimeService{

@Override
public void run() {}

@Override
public void add(String name) {}

@Override
public void delete(String name) {}

@Override
public void update(String name) {}

@Override
public void query(String name) {}

@Override
public void timer() {}
}

内部类

内部类就是在类的内部在定义一个类,比如,A类中定义一个B类,B类相对A类来说就是内部类,A类相对B类就是外部类。

  • 成员内部类
  • 静态内部类
  • 局部内部类
  • 匿名内部类
  • Title: 面向对象编程(OOP,Object-Oriented Programming)
  • Author: 茴香豆
  • Created at : 2024-06-04 10:38:42
  • Updated at : 2024-06-04 23:08:35
  • Link: https://hxiangdou.github.io/2024/06/04/Java-5/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments