前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java入门教程-面向对象

Java入门教程-面向对象

作者头像
哈德森
发布2023-04-07 16:24:12
2150
发布2023-04-07 16:24:12
举报
文章被收录于专栏:哈德森的梦哈德森的梦

面向对象和面向过程的思想对比

  • 面向过程编程(Procedure Oriented Programming):是一种以过程为中心的编程思想,实现功能的每一步,都是自己实现的
  • 面向对象编程(Object Oriented Programming):是一种以对象为中心的编程思想,通过指挥对象实现具体的功能对象:指客观存在的事物(万物皆对象)

1、类和对象

类是对现实生活中一类具有 共同属性 和 行为 的事物的抽象

“类”是对事物,也就是对象的一种描述,可以将类理解为一张设计图,根据设计图,可以创建出具体存在的事物

类的组成

  • 属性:该事物的各种特征
  • 行为:该事物存在的功能(能够做的事情)
  • 对象:是能够看得到摸得着的真实存在的实体

类是对对象的描述 对象是类的实体 一个类可以创建出多个对象

类的定义

类的组成:属性和行为

  • 属性:在代码中通过成员变量来体现(类中方法外的变量)
  • 行为:在代码中通过成员方法来体现

类的定义步骤

  1. 定义类
  2. 编写类的成员变量
  3. 编写类的成员方法
代码语言:javascript
复制
public class 类名{
    // 成员变量
    变量1的数据类型 变量1;
    String name;		// 未赋值默认null
    变量2的数据类型 变量2;
    int age;			// 未赋值默认0
    ......
    // 成员方法 方法1
    public void study(){
        System.out.println("学习");
    }
    方法2;
    ......
}

对象的创建和使用

  • 创建对象格式:类名 对象名 = new 类名();
  • 使用对象使用成员变量:对象名.变量名使用成员方法:对象名.方法名();

案例:定义一个类,然后定义一个手机测试类,在手机测试类中通过对象完成成员变量和成员方法的使用

代码语言:javascript
复制
public class Phone{
    // 成员变量:品牌、价格、....
    String brand;
    int price;
    // 成员方法:打电话、发短信、....
    public void call(String name){
        System.out.println("给" + name + "打电话");
    }
    public void sendMessage(){
        System.out.println("群发短信");
    }
}

2、对象内存图

单个对象内存图

图片[1]-Java入门教程-面向对象-哈德森的梦
图片[1]-Java入门教程-面向对象-哈德森的梦

两个对象内存图

图片[2]-Java入门教程-面向对象-哈德森的梦
图片[2]-Java入门教程-面向对象-哈德森的梦

两个引用指向同一对象内存图

图片[3]-Java入门教程-面向对象-哈德森的梦
图片[3]-Java入门教程-面向对象-哈德森的梦

垃圾回收

当堆内存中,对象 或 数组产生的地址,通过任何方式都不能被找到后,就会被判定为内存中的“垃圾”

垃圾会被Java垃圾回收器,在空闲的时候自动进行清理

成员变量和局部变量

  • 成员变量:类中方法外的变量;存放于堆内存;随着对象的存亡而存亡;有默认的初始化值
  • 局部变量:方法中的变量;存放于栈内存;随着方法调用存在,方法调用完毕结束;无默认初始化值,必须先定义、赋值再使用

3、封装

private关键字:权限修饰符,可以用来修饰成员,来提高数据的安全性

  • 特点:只能在本类当中进行访问,外界需要访问可以定义方法来进行 设置值 和 获取值
  • 针对private修饰的成员变量,如果需要被其他类引用,提供相应的操作
    • 提供get变量名();方法,用于获取成员变量的值,方法用public修饰
    • 提供set变量名();方法,用于设置成员变量的值,方法用public修饰
代码语言:javascript
复制
// 新建Student类
public class Student{
    private String name;
    private int age;
    
    public void setName(String n){
        name = n;
    }
    public String getName(){
        return name;
    }
    public void setAge(int a){
        age = a;
    }
    public int getAge(){
        return age;
    }
    public void show(){
        System.out.println(name + age);
    }
}

this关键字:可以调用本类的成员(变量,方法),解决局部变量和成员变量重名问题

  • 局部变量和成员变量如果重名,Java使用的是就近原则
  • this代表所在类的对象引用,方法被哪个对象调用,this就代表哪个对象
代码语言:javascript
复制
public class Student{
    private int age;
    public void method(int age){
        this.age = age;			// 添加this关键字,使前一个age成为成员变量,再将局部变量age赋值过去
    }
}

this内存原理

img
img

封装

  • 面向对象三大特征之一(封装、继承、多态)
  • 隐藏实现细节,仅对外暴露公共的访问方式(类似于插线板)

常见体现:

  • 将 代码 抽取到 方法 中,是对代码的一种封装;将 属性 抽取到 类 中,是对 数据 的一种封装
  • 私有的成员变量,提供set和get方法

好处

  • 提高了代码的安全性
  • 提高了代码的复用性

4、构造方法

构建、创造对象的时候,所调用的方法

格式

  1. 方法名与类名相同,大小写也要一致
  2. 没有返回值类型,连void也没有
  3. 没有具体的返回值(不能由return带回结果数据)
代码语言:javascript
复制
public class Student{
    public Student(){
        System.out.println("这是Student类的构造方法");
    }
}

执行时机

  1. 创建对象的时候调用,每创建一次对象,就会执行一次构造方法
  2. 不能手动调用构造方法

作用:用于给对象的数据(属性)进行 初始化

代码语言:javascript
复制
class Student{
    private int age;
    public Student(int age){
        this.age = age;
    }
}

注意事项

  • 如果没有定义构造方法,系统将给出一个默认的无参数的构造方法
  • 如果定义了构造方法,系统将不再提供默认的构造方法

标准类的代码编写和使用

代码语言:javascript
复制
/*
	JavaBean类:封装数据的类
*/
public class Student{
    // 私有变量
    private String name;
    private int age;
    
    // 无参数构造方法
    public Student(){}
    //有参数构造方法
    public Student(String name, int age){
        this.name = name;
        this.age = age;
    }
    
    //set/get方法
    public void setName(String name){
        this.name = name;
    }
    
    public String getName(){
        return name;
    }
    
    public void setAge(int age){
        this.age = age;
    }
    
    public String getAge(){
        return age;
    }
}

5、分类和static

5.1. 分类思想

分类思想:分工协作,专人干专事

  • domain类:实体类,封装对应的实体信息
  • Dao类:(Data Access Object缩写)用于访问存储数据的数组或集合(数据库)
  • Service类:用来进行业务逻辑的处理(例如:判读录入的id是否存在)
  • Controller类:和用户打交道(接收用户需求,采集用户信息,返回数据给用户)
5.2. 分包思想

分包思想:如果将所有的类文件都放在同一个包下,不利于管理和后期维护

对于不同功能的类文件,可以放在不同的包(本质上就是文件夹)下进行管理

创建包(单级包、多级包)

  • 多级包之间使用”.”进行分割
  • 多级包的定义规范:公司的网站地址翻转(去掉www)
  • 比如:www.hellocode.top后期所定义的包结构就是:top.hellocode.其他的包名。
  • 包的命名规则:英文字母都是小写

包的定义

  • 使用package关键字定义包
  • 格式:package 包名;(如果是多级包,中间用”.”进行分割)

包的注意事项

  • package语句必须是程序的第一条可执行代码
  • package语句在一个Java文件中只能有一个
  • 如果没有package,默认表示无包名

类与类之间的访问

  • 同一个包下的访问不需要导包,直接使用即可
  • 不同包下的访问
    1. import 导包后访问
    2. 通过全类名(包名+类名)访问应用场景:多个包下,出现了相同的类名,就可以使用这种方式进行区分

注意事项

import、package、class三个关键字的摆放位置存在顺序关系

  • package必须是程序的第一条可执行代码
  • import需要写在package下面
  • class需要在import下面
5.3. static关键字

static关键字是静态的意思,修饰符,可以修饰成员变量、成员方法

  • 被static修饰的成员变量,一般叫做静态变量
  • 被static修饰的成员方法,一般叫做静态方法

特点

  • 被类所有的对象共享,是我们判断是否使用静态关键字的条件
  • 随着类的加载而加载,优先于对象存在,对象需要类被加载后,才能创建
  • 可以通过类名调用,也可以通过对象名调用(推荐使用类名调用)

注意

  • 静态方法中,只能访问静态成员(成员变量、成员方法)
  • 静态方法中,没有this关键字

6、继承

让 类与类之间产生关系(子父类关系),子类可以直接使用父类中非私有的成员

  • 格式:public class 子类名 extends 父类名{}
  • 范例:public class Zi extends Fu{}
  • Fu:是父类,也被称为基类、超类
  • Zi:是子类,也被称为派生类
6.1. 优劣

优点

  • 提高了代码的复用性
  • 提高了代码的维护性
  • 让类与类之间产生了关系,是多态的前提

弊端

  • 继承是侵入性的
  • 降低了代码的灵活性

继承关系,导致子类 必须 拥有父类非私有属性和方法,让子类自由的世界中多了些约束

  • 增强了代码的耦合性(代码与代码之间存在的关联都可以称之为“耦合”)程序设计追求“高内聚,低耦合”

应用场景

  • 当类与类之间,存在相同(共性)的内容,并且产生了is am的关系,就可以考虑使用继承,来优化代码

Java继承的特点

  • Java只支持单继承,不支持多继承,但支持多层继承
6.2. 成员变量

访问顺序

  1. 在子类自身局部范围找
  2. 在子类自身成员范围找
  3. 在父类成员范围找

如果子父类中,出现了重名的成员变量,通过 就近原则 ,会优先使用子类的 如果一定要使用父类的,可以通过super关键字进行区分

super关键字

  • superthis关键字的用法相似
  • this:代表本类对象的引用
  • super:代表父类存储空间的标识(可以理解为父类对象引用)
6.3. 方法重写

在继承体系中,子类出现了和父类中一模一样的方法声明,可以在子类中对父类方法进行重写

应用场景

当子类需要父类的功能,而功能主体子类有自己特有内容,可以重写父类中的方法,这样,既沿袭了父类的功能,又定义了子类特有的内容

区别

  • 方法重写:在继承体系中,子类出现了和父类一模一样的方法声明(方法名,参数列表,返回值类型)
  • 方法重载:在同一个类中,方法名相同,参数列表不同,与返回值无关

方法重写是子类对父类方法的增强,方法重载是针对同一个方法名的不同参数做扩展

注意事项

  • 父类中私有方法不能被重写
  • 父类静态方法,子类必须通过静态方法进行重写严格来说,静态方法不能被重写!如果子类中,也存在一个一模一样的方法,可以理解为子类将父类中同名的方法隐藏了起来,并非是方法重写!
  • 父类非静态方法,子类也必须通过非静态方法进行重写
  • 子类重写父类方法时,访问权限必须大于等于父类
6.4. 权限修饰符

修饰符

同一个类中

同一个包中子类无关类

不同包的子类

不同包的无关类

private

默认

protected

public

6.5. 构造方法

子类中所有的构造方法默认都会访问父类中无参的构造方法

子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据(子类在初始化前,一定要先完成父类的初始化)

  • 构造方法的第一条语句默认都是:super();
  • 注意:如果我们编写的类,没有手动指定父类,系统也会自动继承Object(Java继承体系中的最顶层父类)

访问特点

  • 如果父类中没有空参构造方法,只有带参构造方法,会出现错误
  • 可以在子类通过super,手动调用父类的带参构造方法

注意:this()super()调用构造方法时,必须放在构造方法的第一行有效语句,并且二者不能共存

7、抽象类

  • 抽象方法:将共性的行为(方法),抽取到父类之后,发现该方法的实现逻辑无法在父类中给出具体明确,该方法就可以定义为抽象方法。
  • 抽象类:如果一个类中存在抽象方法,那么该类就必须声明为抽象类。

使用abstract修饰并且没有方法体的方法叫做抽象方法。包含抽象方法的类一定是抽象类

定义格式

  • 抽象方法:public abstract 返回值类型 方法名(参数列表);
  • 抽象类:public abstract class 类名{}
7.1. 注意事项
  • 抽象类不能实例化(创建对象)
  • 抽象类中有构造方法(在创建子类对象时,初始化抽象类自动调用)
  • 抽象类的子类
    • 要么重写父类中所有的抽象方法
    • 要么将自己也变成一个抽象类(了解)
  • 抽象类中的方法
    • 抽象类中可以没有抽象方法,但是有抽象方法的类一定是抽象类
7.2. 模板设计模式
  • 设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。 通俗来说就是写代码的风格
  • 模板设计模式:把抽象整体就可以看做成一个模板,模板中不能决定的东西定义成抽象方法 让使用模板的类(继承抽象类的类)去重写抽象方法实现需求
  • 优势:模板已经定义了通用结构,使用者只需要关心自己需要实现的功能即可
7.3. final关键字
  • 修饰方法:表明该方法是最终方法,不能被重写
  • 修饰变量:表明该变量是常量,不能再次被赋值
    • 修饰基本数据类型变量:其值不能被更改
    • 修饰引用数据类型变量:地址值不能被更改,但是可以修改对象的属性值
    • final修饰成员变量,需要在创建的时候直接赋值或者在构造方法结束之前完成赋值
  • 修饰类:表明该类是最终类,不能被继承

常量的命名规范

  • 如果是一个单词,所有字母大写
  • 如果是多个单词,所有字母大写,每个单词中间使用下划线_分隔

8、代码块

在Java中,使用{}括起来的代码都被称为代码块

分类

局部代码块

  • 位置:方法中定义
  • 作用:限定变量的生命周期,及早释放,提高内存利用率

构造代码块

  • 位置:类中方法外定义
  • 特点:每次构造方法执行的时候,都会执行该代码块中的代码,并且在构造方法执行前执行
  • 作用:将多个构造方法中相同的代码,抽取到构造代码块中,提高代码的复用性

静态代码块

  • 位置:类中方法外定义
  • 特点:需要通过static关键字修饰,随着类的加载而加载,并且只执行一次
  • 作用:在类加载的时候做一些数据初始化的操作

9、接口

当一个类中所有方法都是抽象方法的时候,我们就可以将其定义为接口 接口也是一种引用数据类型,它比抽象类还要抽象

意义

  • 规则的定义
  • 程序的扩展性

定义和特点

  • 使用interface关键字:public interface 接口名{}
  • 接口不能实例化(创建对象)
  • 接口和类之间是实现关系,通过implements关键字表示public class 类名 implements 接口名{}
  • 支持单接口实现,也支持多实现public class 类名 implements 接口名1,接口名2{}

接口的子类(实现类)

  • 要么重写接口中的所有抽象方法
  • 要么是抽象类

成员的特点

  • 成员变量只能是常量,系统会默认加入三个关键字:publicstaticfinal
  • 构造方法

接口中不存在构造方法

  • 成员方法

只能是抽象方法(JDK7以前),系统会默认加入两个关键字:publicabstract

JDK8中接口成员的特点 允许接口中定义非抽象方法,但是需要使用关键字default修饰,这些方法就是默认方法 定义格式:public default 返回值类型 方法名(参数列表){} 默认方法不是抽象方法,所以不强制重写,但是可以被重写,重写的时候去掉default关键字 public可以省略,但是default不能省略 如果实现了多个接口,多个接口中存在相同的方法声明,子类就必须对该方法进行重写

使用思路

  • 如果发现一个类中所有的方法都是抽象方法,那么就可以将该类改进为一个接口
  • 涉及到了接口大面积更新方法,而不想去修改每一个实现类,就可以将更新的方法,定义为带有方法体的默认方法
  • 希望默认方法的调用更加简洁,可以考虑设计为static静态方法(需要去掉default关键字)
  • 默认方法中出现了重复的代码,可以考虑抽取出一个私有方法(需要去掉default关键字)

类和接口的关系

  • 类和类的关系继承关系,只能单继承,但是可以多层继承
  • 类和接口的关系实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
  • 接口和接口的关系继承关系,可以单继承,也可以多继承

10、多态

同一个对象,在不同时刻表现出来的不同形态

前提

  • 要有(继承 / 实现)关系
  • 要有方法重写
  • 要有父类引用,指向子类对象

成员访问特点

  • 构造方法:同继承一样,子类会通过super访问父类构造方法
  • 成员变量:编译看(等号)左边(父类),执行看(等号)右边(父类)
  • 成员方法:编译看(等号)左边(父类),执行看(等号)右边(子类)

优劣点

  • 好处:提高了程序的扩展性具体体现:定义方法的时候,使用父类型作为参数,该方法就可以接收这父类的任意子类对象
  • 弊端:不能使用子类的特有功能

如果被转的引用类型变量,对应的实际类型和目标类型不是同一种类型,那么在转换的时候就会出现 ClassCastException 异常

instanceof关键字

  • 使用格式:变量名 instanceof 类型
  • 通俗的理解:判断关键字左边的变量,是否是右边的类型,返回boolean类型结果
  • 可以在强制转型前使用该关键字进行判断,以增强程序的健壮性

11、内部类

就是在一个类中定义一个类。举例:在A类的内部定义一个B类,B类就被称为内部类

11.1. 成员内部类
  • 位置:在类的成员位置
  • 创建内部类对象的格式:外部类名.内部类名 对象名 = new 外部类对象().new 内部类对象()

内部类的访问特点

  • 内部类可以直接访问外部类的成员,包括私有
  • 外部类要访问内部类的成员,必须创建对象

也属于成员,可以被一些修饰符修饰

  • private私有成员内部类访问:在自己所在的外部类中创建对象访问
  • static静态成员内部类访问格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();静态成员内部类中的静态方法:外部类名.内部类名.方法名();
11.2. 局部内部类
  • 概述:局部内部类是在方法中定义的类,所以外界无法直接使用,需要在方法内部创建对象并使用,该类可以直接访问外部类的成员,也可以访问方法内的局部变量
  • 位置:类的局部位置
11.3. 匿名内部类

本质上是一个特殊的局部内部类(定义在方法内部)【使用次数远远大于成员内部类和局部内部类】

  • 前提:需要存在一个接口或类
  • 格式new 类名或者接口名(){ 重写方法; }
  • 理解:将继承\实现,方法重写,创建对象三个步骤放在了一步进行
  • 使用场景当方法的形式参数是接口或者抽象类时,可以将匿名内部类作为实际参数进行传递

12、Lambda表达式

Lambda表达式,是对匿名内部类进行了优化,代码更少,关注点更加明确

函数式编程思想

在数学中,函数就是有输入量、输出量的一套计算方案,也就是“拿数据做操作”

面向对象思想强调“必须通过对象的形式来做事情”

函数式思想则尽量忽略面向对象的复杂语法:“强调做什么,而不是以什么形式去做”

Lambda表达式就是函数式思想的体现

标准格式

  • 格式:(形式参数) -> {代码块}
  • 形式参数:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
  • ->:由英文中画线和大于符号组成,固定写法,代表指向动作
  • 代码块:是我们具体要做的事情,也就是以前写的方法体内容

使用前提

  • 有一个接口
  • 接口中有且仅有一个抽象方法

练习

  1. 编写一个接口(ShowHandler)
  2. 在该接口中存在一个抽象方法(show),该方法是无参数无返回值
  3. 在测试类(ShowHandlerDemo)中存在一个方法(useShowHandler)方法的参数是ShowHandler类型的在方法内部调用了ShowHandler的show方法
代码语言:javascript
复制
public class TestLambda{
    public static void main(String[] args){
        // 匿名内部类实现
        useShowHandler(new ShowHandler(){
            @Override
            public void show(){
                System.out.println("我是匿名内部类中的show方法");
            }
        });
        
        // Lambda实现
        useShowHandler(() -> {System.out.println("我是匿名内部类中的show方法");});
    }
    public static void useShowHandler(ShowHandler showHandler){
        showHandler.show();
    }
}

interface ShowHandler{
    void show();
}
  1. 首先存在一个接口(StringHandler)
  2. 在该接口中存在一个抽象方法(printMessage),该方法是有参数无返回值
  3. 在测试类(StringHandlerDemo)中存在一个方法(useStringHandler),方法的参数是StringHandler类型的,在方法内部调用了StringHandlerprintMessage方法
代码语言:javascript
复制
public class StringHandlerDemo{
    public static void main(String[] args){
        // 匿名内部类实现
        useStringHandler(new StringHandler(){
            @Override
            public void printMessage(String msg){
                System.out.println("我是匿名内部类." + msg);
            }
        });
        
        // Lambda实现
        useStringHandler((String msg) -> {System.out.println("我是Lambda" + msg);});
    }
    
    public static void useStringHandler(StringHandler stringHandler){
        stringHandler.printMessage("坚持学习!");
    }
}

interface StringHandler{
    void printMessage(String msg);
}

省略规则

  • 参数类型可以省略,但是有多个参数的情况下,不能只省略一个
  • 如果参数有且仅有一个,那么小括号可以省略
  • 如果代码块的语句只有一条,可以省略大括号和分号,甚至是return
代码语言:javascript
复制
useStringHandler(msg -> System.out.println("我是Lambda" + msg));

Lambda表达式和匿名内部类的区别

所需类型不同

  • 匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
  • Lambda:只能是接口

使用限制不同

  • 如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类
  • 如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式

实现原理不同

  • 匿名内部类:编译之后,产生一个单独的.class字节码文件
  • Lambda表达式:编译之后,没有一个单独的.class字节码文件,对应的字节码会在运行的时候动态生成
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、类和对象
  • 2、对象内存图
  • 3、封装
  • 4、构造方法
  • 5、分类和static
    • 5.1. 分类思想
      • 5.2. 分包思想
        • 5.3. static关键字
        • 6、继承
          • 6.1. 优劣
            • 6.2. 成员变量
              • 6.3. 方法重写
                • 6.4. 权限修饰符
                  • 6.5. 构造方法
                  • 7、抽象类
                    • 7.1. 注意事项
                      • 7.2. 模板设计模式
                        • 7.3. final关键字
                        • 8、代码块
                        • 9、接口
                        • 10、多态
                        • 11、内部类
                          • 11.1. 成员内部类
                            • 11.2. 局部内部类
                              • 11.3. 匿名内部类
                              • 12、Lambda表达式
                              相关产品与服务
                              短信
                              腾讯云短信(Short Message Service,SMS)可为广大企业级用户提供稳定可靠,安全合规的短信触达服务。用户可快速接入,调用 API / SDK 或者通过控制台即可发送,支持发送验证码、通知类短信和营销短信。国内验证短信秒级触达,99%到达率;国际/港澳台短信覆盖全球200+国家/地区,全球多服务站点,稳定可靠。
                              领券
                              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档