Java基础教程 - 7 面向对象-2

更好的阅读体验:点这里www.doubibiji.com
更好的阅读体验:点这里www.doubibiji.com
更好的阅读体验:点这里www.doubibiji.com

7 面向对象

7.2 封装

面向对象编程,是一种编程思想,简单的理解就是:先有模板,也就是类,根据模板去创建实例,也就是对象,然后使用对象来完成功能开发。

我们经常说面向过程编程和面向对象编程,面向过程编程关注的是实现功能的步骤,面向对象编程更关注的是谁来实现功能。

面向对象编程有3大特性:

  • 封装
  • 继承
  • 多态

下面依次开始讲起。

在前面我们创建类,在类中定义了属性和方法,通过属性和方法来对现实世界的事物进行抽象的描述。

一个事物有很多的属性和方法,但是并不是所有属性和方法都需要开放出来。例如我们定义了一个手机类,我们可以使用手机打电话、拍照等,但是我们并不关心手机电压,驱动信息,也不关心内存的分配,CPU的调度等,虽然这些都属于手机的属性和行为。

我们可以将用户不关心的属性和方法封装并隐藏起来,只给类内部的方法调用,例如上网会用到4G模块,但是不是由用户来使用4G模块,而是由手机上网的功能开调用4G模块,只开放用户直接使用的信息和功能。

那么回过头来看,什么是封装?

它指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象的内部信息。如果要访问这些信息,需要通过该类所提供的方法来实现对内部信息的操作和访问。

1 私有属性和方法

那么怎么将不想暴露的变量和方法隐藏起来呢,就需要用到私有成员变量和私有成员方法。

定义私有成员和私有方法的方式是使用 private 关键字修饰变量和方法。

举个栗子:

class Phone {
    public String producer = "华为"; 	 // 手机品牌
    private int voltage = 12; 		// 电压

    /**
     * 定义一个公共方法
     */
    void call() {
        System.out.println("打电话");
        System.out.println("手机品牌: " + this.producer);
        System.out.println("手机电压: " + this.voltage);
    }

    /**
     * 定义一个私有方法
      */
    private void getRunVoltage() {
        System.out.println("当前电压:" + this.voltage);
    }
}

public class ObjectTest {
    public static void main(String[] args) {
        Phone phone = new Phone();
        phone.call();

        phone.producer = "小米";
        // phone.voltage = 24;     // 私有变量,类外部无法访问
        phone.call();
        // phone.getRunVoltage();   // 私有方法,类外部无法访问
    }
}

上面定义了私有属性 voltage 和私有方法 getRunVoltage,使用 private 关键字修饰。私有属性和私有方法只能在类内部的方法中调用,在类的外部不能通过对象来调用。

如果不想暴露的属性和方法可以定义为私有成员。私有属性和私有方法只能在类内部的方法中调用,不能通过对象来调用。

执行结果:

打电话
手机品牌:华为
手机电压:12
打电话
手机品牌:小米
手机电压:12

2 getter和setter

我们前面说到,封装是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象的内部信息。如果要访问这些信息,需要通过该类所提供的方法来实现对内部信息的操作和访问。

在面向对象编程思想中,我们一般会将所有的属性都设置为私有的,然后为每个属性提供两个对应的方法,分别用来获取和设置对应的属性,这两个方法称为 getter和setter 方法。

举个栗子:

Phone.java

class Phone {
    private String producer = "华为"; 	 // 手机品牌
    private int voltage = 12; 		// 电压

    public Phone(String producer, int voltage) {
        this.producer = producer;
        this.voltage = voltage;
    }

    public String getProducer() {
        return producer;
    }

    public void setProducer(String producer) {
        this.producer = producer;
    }

    public int getVoltage() {
        return voltage;
    }

    public void setVoltage(int voltage) {
        this.voltage = voltage;
    }

    // 其他方法....
}

/**
 * 测试类
 */
public class MethodTest {
    public static void main(String[] args) {
        Phone phone = new Phone("华为", 12);
        System.out.println(phone.getProducer()); // 通过getter方法获取变量,并不是直接访问变量
        System.out.println(phone.getVoltage());

        phone.setProducer("小米"); // 通过setter方法设置变量,并不是直接给变量赋值
        phone.setVoltage(24);
        System.out.println(phone.getProducer());
        System.out.println(phone.getVoltage());
    }
}

在上面为属性 producervoltage 定义了 get 和 set 方法,get 方法以 get 开头,后跟属性名,遵循方法命名规则。set 方法类似,get 方法有返回值,没有参数,set 方法接收参数,没有返回值。

通过 getter 和 setter 来访问私有属性和为私有属性赋值。这样做的话,严格控制了属性获取和设置的入口,如果通过 对象.属性 来修改,代码很多的时候完全会不知道在哪里修改了属性导致出现了问题。另外我们可以在setter方法中对属性的设置进行限制。

执行结果:

华为
12
小米
24

7.3 包

在实际的项目中,我们一般会将每个类单独定义到一个 .java 文件中,项目中会定义很多很多的类,如果这些类都放在一个目录下,会变得难管理,还可能存在同名的类。为了更好的组织规划和对控制类的访问权限,我们可以使用 来对类进行管理。

1 package包

包名是一个以小写字母组成的标识符,通常采用逆域名的方式来命名,例如逗比笔记的域名是 doubibiji.com ,那么包名就是com.doubibiji.项目名称。这种命名方式有助于避免包名冲突。

例如,我们有一个学生管理系统的项目,那么包名可以定义为 com.doubibiji.stumanagement 。因为一个项目中,不同的类负责不同的功能,还可能进行分层的设计,所以在这个包名下,还可以再进行子包的划分,将不同功能的类规划到不同的子包中。

在 IDEA 中可以直接右键 New 来创建包。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

包是有层级的,每个 . 表示一层,在硬盘上其实就是一层文件夹。

通过不同的包,来划分系统中的功能和设计结构,让系统更加清晰,例如下面的项目,将不同的类划分到不同的子包下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这样项目的结构更为清晰,更好管理。

在每个类中,第一条代码就是 package,表示当前的类所在的包名。每个包中不能存在同名的类。


在 JDK 中不同功能的类也是划分到不同的包中,下面是一些常用的 Java API 所在的包:

  • java.lang:包含一些 Java 语言的核心类,如 String、Math、Integer、System 和 Thread,提供常用功能;
  • java.net:包含执行与网络相关的操作的类和接口。
  • java.io:包含能提供多种输入/输出功能的类。
  • java.util:包含一些实用工具类,如定义系统特性、接口的集合框架类、使用与日期日历相关的函数。
  • java.text:包含了一些 java 格式化相关的类
  • java.sql:包含了 java 进行 JDBC 数据库编程的相关类/接口
  • java.awt:包含了构成抽象窗口工具集(abstractwindowtoolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。

2 import引入

因为不同的类放在不同的包中,在使用其他包中的类或接口,就需要使用 import 进行引入。

在 Java中,如果没有显式地使用 import 语句,编译器会自动导入 java.lang包。这个包包含了 Java 语言的核心类,其他包中的类都需要手动导入。

下面是常用用法:

导入单个类

举个栗子:

在上面的代码中,在 StudentDao.java 中使用 Student 类,就需要使用 import 进行引入:

package com.doubibiji.stumanagement.dao;

// 引入Student类
import com.doubibiji.stumanagement.pojo.Student;

public class StudentDao {
    public static void main(String[] args) {
        Student student = new Student();
    }
}
导入包中所有的类

如果要导入某个包下所有的类,可以使用星号(*),但这太推荐这种用法。

// 导入java.util包下所有的类
import java.util.*;

public class ImportTest {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
    }
}
静态导入

静态导入允许导入一个类或接口中的静态成员(静态方法、静态字段和静态内部类)。

举个例子:

假设在一个类中有静态属性和静态方法:

package com.doubibiji.utils;

public class Utils {
    // 静态属性
    public static final int MAX_VALUE = 99;

    /**
     * 静态方法
     */
    public static int max(int a, int b) {
        return Math.max(a, b);
    }
}

那么在其他的包中,可以使用 import static 单独引入 Utils 中的静态属性和方法:

// 引入静态变量
import static com.doubibiji.utils.Utils.MAX_VALUE;
// 引入静态方法
import static com.doubibiji.utils.Utils.max;

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

        System.out.println(MAX_VALUE);
        System.out.println(max(3, 5));
    }
}

7.4 权限修饰符

我们前面已经使用了权限修饰符 publicprivate

在 Java 中权限修饰符一种有四种:publicprotected缺省(就是没有修饰符)private

它们可以用来修饰属性、方法、构造方法、内部类(类内部的类),如果修饰普通类的话,只能使用:缺省、public

他们对访问权限的限制如下:

修饰符类内部同一个包不通包的子类中同一个工程(项目)
private可访问
缺省可访问可访问
protected可访问可访问可访问
public可访问可访问可访问可访问

举个栗子:

com.doubibiji.hellojava.pojo 包下有 Student 类:

package com.doubibiji.hellojava.pojo;

public class Student {
    
    private String sid;
    String name;
    public int age;
    
}

那么同样在 com.doubibiji.hellojava.pojo 包下有 StudentTest 类中:

package com.doubibiji.hellojava.pojo;

public class StudentTest {
    public static void main(String[] args) {
        Student student = new Student();

        // System.out.println(student.sid);    // private无法访问
        System.out.println(student.name);   // 缺省,同一个包下可以访问
        System.out.println(student.age);    // public,同一个包下可以访问
    }
}

如果 StudentTest 类在不同的包下,例如在 com.doubibiji.hellojava.utils 包下:

package com.doubibiji.hellojava.utils;
import com.doubibiji.hellojava.pojo.Student;

public class StudentTest {
    public static void main(String[] args) {
        Student student = new Student();

        // System.out.println(student.sid);    // private无法访问
        // System.out.println(student.name);   // 缺省,不通包下无法可以访问
        System.out.println(student.age);    // public,同一个包下可以访问
    }
}

protected 的访问权限是同一个包下可以访问,子类中也可以访问。子类在讲 继承 的时候再讲。

  • 26
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山石岐渡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值