唠唠SE的面向对象-02——封装 原

2. 封装

1) 我们日常使用的电脑主机,把cpu、内存、主板等等都封装到机箱里面去。假如没有机箱的话的出现什么问题?

主机、主板全部都散落在一处,然后开机没有开机按钮,那么需要我们直接操作接跳线才能把电脑开启。

这样子的话假如操作不慎的话,会让机器损坏危险,那么假如用机箱封装起来的话,那么就不需要这样子做了。这体现了封装的---安全特性

2) 你拿电脑去加内存,可以直接给电脑给维修的人。等他加好内存了之后,你拿到的还是那个机箱,里面发生了啥变化你并不知道。

封装的第二个好处---将变化隔离

3) 在机箱里面提供一个开机按钮,而不需要你直接使用跳线开机的话,体现了封装的---便于使用的特性。

4) 只要机箱提供了一个开机的功能,然后无论这个机箱拿到哪里去,都可以使用这个开机的功能。体现了封装的---可重复性的特性。

举个栗子:模拟员工类,看看封装与不封装有什么区别

不使用变量封装:

class Employee {
	String name;
	int age;
}

public class Test {
	public static void main(String[] args) {
		Employee employee = new Employee();
		employee.name = "辣条";
		employee.age = 24;
		System.out.println(employee.name);
	}
}

使用变量封装:

class Employee {
    private String name;
    private int age = 24;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
}

public class Test {
    public static void main(String[] args) {
        Employee employee = new Employee();
        //employee.name = "辣条"; -- 编译报错,变量被定义为private,不允许访问
        employee.setName("辣条");
        //employee.setAge(24); -- 报错,没有开放setter方法,不能修改age的值
        System.out.println(employee.getName());
    }
}

很容易发现被我注释掉的那两行都在编译期报错了,这就体现了封装的几个特性。

再举个栗子,说明封装的易操作:模拟一个手机,提供一个可以接收信息的方法

class Phone {
    private String name;
    private int price = 5000;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getPrice() {
        return price;
    }

    /**
     * 接收信息
     * @author LinkedBear
     * @param message 发送的信息
     */
    public void getMessage(String message) {
        System.out.println("价值" + price + "元的" + name + " 收到信息:" + message);
    }
}

public class Test {
    public static void main(String[] args) {
        Phone phone = new Phone();
        phone.setName("高端大气上档次的诺基亚黄屏手机");
        phone.getMessage("尊敬的用户您好,您的智商不足,请及时充值。。。");
    }
}

//运行结果:
//价值5000元的高端大气上档次的诺基亚黄屏手机 收到信息:尊敬的用户您好,您的智商不足,请及时充值。。。

我们再重复一遍 ̄へ ̄:

封装的好处:安全性、变化隔离、便于使用、可重复性

PS:封装之后的属性可以提供getter与setter方法来获取和修改。(setter还有一些东西,咱到后面说this的时候再唠)

咱来思考一个问题:

如果我们做这么一个功能:获取指定毫秒值对应的时间、日期等多种格式(可能部分代码不容易理解,我尽量把注释写清楚):

import java.text.SimpleDateFormat;
import java.util.Date;

public class Demo3 {
    public static void main(String[] args) {
        long time = System.currentTimeMillis(); // 用该方法可以获取当前时刻,精确到毫秒
        SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日"); // 用日期格式化类转换,格式为1970年01月01日
        SimpleDateFormat format2 = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒"); // 用日期格式化类转换,格式为1970年01月01日 12时00分00秒
        Date date = new Date(time); // 把毫秒值变成一个日期的对象
        System.out.println(format.format(date)); //转换,打印输出
        System.out.println(format2.format(date)); //转换,打印输出
        Date date2 = new Date();
        System.out.println(format.format(date2));
        System.out.println(format2.format(date2));
    }
}

//运行结果:
//2018年01月29日
//2018年01月29日 11时30分17秒
//2018年01月29日
//2018年01月29日 11时30分17秒

发现代码很多都重复了!

封装的第二种用途:提取相同/相似的代码,封装成一个方法

import java.text.SimpleDateFormat;
import java.util.Date;

public class Demo {
    public static void main(String[] args) {
        long time = System.currentTimeMillis(); // 用该方法可以获取当前时刻,精确到毫秒
        parseTimeToDate(time);
    }
    
    /**
     * 将一个毫秒值转换成年月日的字符串
     * @author LinkedBear
     * @param time 代表指定时刻的毫秒值
     */
    public static void parseTimeToDate(Long time) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒"); // 用日期格式化类转换,格式为1970年01月01日 12时00分00秒
        Date date = new Date(time); // 把毫秒值变成一个日期的对象
        System.out.println(format.format(date)); //转换,打印输出
    }
}

//运行结果:
//2018年01月29日 11时22分31秒

这样封装固然好,但是容易出现了一个新的问题:

如果我有一组实现效果相似的功能,总不能让我叫方法1,方法2,方法3吧,这也太low了!

所以,我们引入了下面的概念——

方法的重载Overload:

方法名相同,但传入参数的个数、类型、顺序不同,都可以用同名方法。

那我们再举一个栗子:上面的黄屏手机中新添加一个播放歌曲的无参方法,再添加一个指定播放曲目的有参方法

class Phone {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    /**
     * 无参方法,默认播放社会摇 ̄へ ̄
     * @author LinkedBear
     */
    public void music() {
        System.out.println(name + "正在播放:社会摇。。。");
    }
    
    /**
     * 带参方法,播放指定歌曲
     * @author LinkedBear
     * @Time 2018年1月29日 上午11:36:39
     * @param musicName
     */
    public void music(String musicName) {
        System.out.println(name + "正在播放:" + musicName);
    }
}

public class Test {
    public static void main(String[] args) {
        Phone phone = new Phone();
        phone.setName("高端大气上档次的诺基亚黄屏手机");
        phone.music();
        phone.music("一人饮酒醉");
    }
}

//运行结果:
//高端大气上档次的诺基亚黄屏手机正在播放:社会摇。。。
//高端大气上档次的诺基亚黄屏手机正在播放:一人饮酒醉

--------------------------------优雅的分割线------------------------------------

放在最后的,是我在实际开发中一直都在用的一个转换工具类,封装和重载的功能还是蛮够用的,贴出来分享一下吧 ̄へ ̄

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 转换工具类,支持时间格式转换、数字格式转换等
 * @author LinkedBear
 */
public class FormatUtil {
    public static final String DATE_PATTERN = "yyyy-MM-dd";
    public static final String TIME_PATTERN = "yyyy-MM-dd HH:mm";
    private static SimpleDateFormat formatDate = new SimpleDateFormat(DATE_PATTERN);
    private static SimpleDateFormat formatTime = new SimpleDateFormat(TIME_PATTERN);
    private static DecimalFormat df = new DecimalFormat("0.00");
    
    /**
     * 标准日期转换yyyy-MM-dd(接收Date)
     * @author LinkedBear
     * @param date
     * @return
     */
    public static synchronized String formatDate(Date date) {
        return formatDate.format(date);
    }
    
    /**
     * 标准日期转换yyyy-MM-dd(接收Long)
     * @author LinkedBear
     * @param date
     * @return
     */
    public static synchronized String formatDate(Long date) {
        return formatDate.format(new Date(date));
    }
    
    /**
     * 标准时间转换yyyy-MM-dd HH:mm(接收Date)
     * @author LinkedBear
     * @param date
     * @return
     */
    public static synchronized String formatMinute(Date date) {
        return formatTime.format(date);
    }
    /**
     * 标准时间转换yyyy-MM-dd HH:mm(接收Long)
     * @author LinkedBear
     * @param date
     * @return
     */
    public static synchronized String formatMinute(Long date) {
        return formatTime.format(new Date(date));
    }
    
    /**
     * 指定转换格式的日期转换(接收Date)
     * @author LinkedBear
     * @param date
     * @param pattern
     * @return
     */
    public static String formatDate(Date date, String pattern) {
        SimpleDateFormat format = new SimpleDateFormat(pattern);
        return format.format(date);
    }
    /**
     * 指定转换格式的日期转换(接收Long)
     * @author LinkedBear
     * @param date
     * @param pattern
     * @return
     */
    public static String formatDate(Long date, String pattern) {
        SimpleDateFormat format = new SimpleDateFormat(pattern);
        return format.format(new Date(date));
    }
    
    /**
     * 标准字符串日期yyyy-MM-dd转成Long
     * @author LinkedBear
     * @param date
     * @return
     */
    public static Long parseStringToLong(String date) {
        try {
            return formatDate.parse(date).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
            return -1L;
        }
    }
    
    /**
     * 字符串时间转成指定格式的Long
     * @author LinkedBear
     * @param date
     * @param pattern
     * @return
     */
    public static Long parseStringToLong(String date, String pattern) {
        SimpleDateFormat format = new SimpleDateFormat(pattern);
        try {
            return format.parse(date).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return -1L;
    }
    
    /**
     * 将金额数值格式化为两位小数
     * @author LinkedBear
     * @param num
     * @return
     */
    public static synchronized String formatMoney(long num) {
        return df.format(num);
    }
    
    /**
     * 将金额数值格式化为两位小数
     * @author LinkedBear
     * @param num
     * @return
     */
    public static synchronized String formatMoney(double num) {
        return df.format(num);
    }
    
    private FormatUtil() {
        
    }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java爬坑系列

【JAVA零基础入门系列】Day3 Java基本数据类型

  前两篇已经将开发环境搭建完成,如果你已经按之前的教程按部就班的完成了部署,那么世界上最优秀的编程语言之一和世界上最优秀的IDE之一已经出现在你的电脑上(此处...

2188
来自专栏ImportSource

是时候忘掉finalize方法了

故事要从jdk11 early access版说起。 近日,发现jdk11发布了一个早鸟版。心想,jdk10刚刚发布没多久(JDK10要来了:下一代 Java...

4248
来自专栏小樱的经验随笔

洛谷 P1200 [USACO1.1]你的飞碟在这儿Your Ride Is He…【字符串+模拟】

P1200 [USACO1.1]你的飞碟在这儿Your Ride Is He… 题目描述 众所周知,在每一个彗星后都有一只UFO。这些UFO时常来收集地球上的忠...

3345
来自专栏康怀帅的专栏

Shell date 命令详解

以给定的格式显示当前时间。 %% 一个文字的 % %a 当前locale 的星期名缩写(例如: 日,代表星期日) %A 当前locale 的星...

3674
来自专栏吾爱乐享

java之学习date类的综合案例-算一下你来到这个世界多少天

1364
来自专栏Spark学习技巧

Flink DataStream编程指南

Flink程序是执行分布式集合转换(例如,filtering, mapping, updating state, joining, grouping, defi...

1.9K7
来自专栏分布式系统和大数据处理

悟透JavaScript

这本书分为了三个部分,第一部分“JavaScript真经”主要讲解JavaScript的一些核心概念,主要是数据类型、函数、原型、对象。并通过在JavaScri...

1234
来自专栏mini188

学习笔记:Hashtable和HashMap

学了这么些天的基础知识发现自己还是个门外汗,难怪自己一直混的不怎么样。但这样的恶补不知道有没有用,是不是过段时间这些知识又忘了呢?这些知识平时的工作好像都是随拿...

2128
来自专栏码洞

天下无难试之ArrayList面试刁难大全

ArrayList可能是Java数据结构中最简单的一种了,即使一个非Java程序员可能也知道这个数据结构,因为所有的语言中都有这样的类似的数据结构。可是在经历过...

942
来自专栏嵌入式程序猿

sizeof应用的小陷阱

本篇笔记主要介绍在项目开发中,使用sizeof的一个要注意的地方。分别在8位机microchip PIC18F46K22, 16位机microchip ds...

3648

扫码关注云+社区

领取腾讯云代金券