Java复习2-对象与类
回顾基础知识过程中遇到的感觉需要记录一下的知识点。
封装
我们设计的class应当尽可能的高内聚,体现为封装的程度。一个class的属性应该只能自己修改,其他class都只是与本class沟通,而不应该有能力修改。比较常见的一个问题是Date属性。
业务开发中经常需要设计class的日期属性,比如birthday, createDate等。
public class User {
private String name;
private Date birth;
public Date getBirth() {
return this.birth;
}
}
我经常设计一个entity,填入字段,然后就直接getter, setter出去,尤其使用lombok后,更是连生成都改自动了。按照封装的要求,这样的做法是不合适的。因为其他class可以获取Date对象,Date对象是可变的。那么,就有可能会产生日期被修改的可能。
如果项目有引入Findbugs的扫描,这个class肯定会被扫描出来的,不应该返回一个可变对象。那么,怎么做才可以避免这个问题?我们确实需要暴露Date啊。
答案是暴露一个不可变的对象。Java8推出了新的日期API,其中LocalDate就是不可变的。用LocalDate替换Date即可。LocalDate就像String一样,没有提供任何可以改变内部属性的方法,所有的修改之类的方法都将会创建一个新的对象。这样,修改操作将不会影响原来的class。
Date对象可以解决,但很多是自己定义的对象,这个怎么办?比如,User有个属性是Role。
public class User {
private String name;
private LocalDate birth;
private Role role;
public Role getRole() {
return this.role;
}
}
和Date类似,当调用getRole之后,外界如果可以修改role的属性,比如把role改成admin,那么本对象就拥有了admin权限了。这是我们不愿看到的。可以模仿LocalDate,把Role的所有修改内部属性的方法关闭。这样,外部无法修改Role,就不会影响到User了。然而,我们web中需要把对象渲染成json发送出去,jackson会根据getter setter去做序列化和反序列化操作。这个setter还不能关闭。
那就只能处理User自己了。user唯一发生风险的地方在于getRole后,把自己内部属性暴露出去了。我们可以getRole的时候给一个新的出去,让其他class随便改都不会影响自己。
public class User {
private String name;
private LocalDate birth;
private Role role;
public Role getRole() {
return (Role) this.role.clone();
}
}
现实是,我们很少关注这样的做法,都是直接返回。而且,也很少遇到错误。这时候可以 忽略findbugs的异常。但,最好的,还是推荐做这样的修改。
方法传参的按值调用
初学Java的时候最容易搞不懂的地方就是传递参数到底是怎么传递的。
在程序设计语言中有关将参数传递给方法(或函数)的一些专业术语。按值调用(call by value)表示方法接收的是调用者提供的值。而按引用调用(call be reference)表示方法接收的是调用者提供的变量地址。一个方法可以修改传递引用所对应的变量值,而不能修改传递值调用所对应的变量值。按...调用(call by)是一个标准的计算机科学术语,它用来描述各种程序设计语言(不只Java)中方法参数的传递方式。
Java程序设计语言总是按值调用。也就是说,方法得到的是所有参数值的一个拷贝,特别是,方法不能修改传递给它的任何参数变量的内容。
int a = 10;
addOne(a)
不管addOne方法具体实现,a最终依旧还是10. 因为当a传递给addOne方法的时候,拷贝了一份a的值给参数,方法中运行过程中都是一份拷贝,不会影响原来的变量。
方法参数共有两种:
- 基本数据类型(数字、布尔值)
- 对象引用
上述demo显示一个方法不可能修改一个基本数据类型的参数。那么对象引用呢?
StringBuilder sb = new StringBuilder();
appendOne(sb);
appendOne执行过程中会对sb产生影响吗?
这就要看具体方法内容了。比如
public void appendOne(StringBuilder sb) {
sb.append("1");
}
那么,我们最终执行完结果肯定sb内容添加了1。而换一个方式,
public void appendOne2(StringBuilder s){
s = new StringBuilder();
s.append("a");
}
这样,方法外面的sb的内容会变成什么?
这个,首先要记住的是Java方法传参都只是传递拷贝。然后,明白传递拷贝的意义

因为s指向的地址和sb相同,故,当s.append的时候,sb的内容也会改变。这也上开头讲述的封装不应返回一个可变变量的原因。任何拿到这个可变变量地址的方法都可以直接修改变量里的属性。那方法2有什么不同?

方法2中,把参数s指向了新地址,那么接下来的任何修改,都将不会影响旧地址。则方法外的sb对应的地址空间也就不会发生变化。这个可以理解为Java传递对象引用的时候只复制了对象引用的地址。
类设计技巧
- 一定要保证数据私有,即封装性;
- 一定要对数据初始化,最好不要依赖系统的默认值,自己给定一个初始值;
- 不要在类中使用过多的基本类型,可以把相关的几个变量合成一个class,转为引用class,另外,能用包装类就不用基本类型;
- 不是所有的成员变量都应该提供对外访问方法,比如创建日期不可以修改;
- 将职责过多的类进行分解;
- 类名和方法名要能够体现他们的职责;
- 优先使用不可变的类。
Java复习2-对象与类的更多相关文章
- 关于Java中的对象、类、抽象类、接口、继承之间的联系
关于Java中的对象.类.抽象类.接口.继承之间的联系: 导读: 寒假学习JavaSE基础,其中的概念属实比较多,关联性也比较大,再次将相关的知识点复习一些,并理顺其中的关系. 正文: 举个例子:如果 ...
- JavaSE复习_2 对象与类
△java中的制表符.'\t'制表符."\t"也可以. △方法内不能再定义一个方法,互相平级. △数组中boolean类型的变量默认为false;char默认为'\u0000'(\ ...
- java基础(二) -对象和类
Java 对象和类 Java作为一种面向对象语言.支持以下基本概念: 多态 继承 封装 抽象 类 对象 实例 方法 重载 对象:对象是类的一个实例(对象不是找个女朋友),有状态和行为.例如,一条狗是一 ...
- java中的对象、类、包、模块、组件、容器、框架、架构的概念入门
在Java中有那么一些概念:对象.类.包.模块.组件.容器.框架.这些概念都有一个共同的特点,就是[容纳]. 对象(Object) 在Java的世界里,对象是通过属性和方法来分别对应事务所具有的静态属 ...
- Java 学习:对象和类
对象和类 从认识的角度考虑是先有对象后有类.对象,是具体的事物.类,是抽象的,是对对象的抽象. 从代码运行角度考虑是先有类后又对象.类是对象的模板. 对象:对象是类的一个实例,有状态和行为. 类:类是 ...
- Java中的对象、类、抽象类、接口的理解
1.对象 对象是个具体的东西,有着明确的属性特征和行为特征. 例如:你手上牵着的女朋友或男朋友就是个具体的对象. 如图中的苏格兰折耳猫,特征是耳朵向下呈折叠状,有着具体的颜色(你看到的颜色),并且和其 ...
- Java第二章----对象和类
从第一章到第二章整整隔了一个月的时间,这速度也是慢的无语了.因为这个月负责开发公司一个SaaS类型APP,忙的昏天暗地终于上线了,这才有时间写个博客.本章还是以概念为主,有点枯燥重在理解. 第一节:对 ...
- java中的对象和类
1.类:类是一个模板,它描述一类对象的行为和状态. 一个类可以包含以下类型变量: 局部变量:在方法.构造方法或者语句块中定义的变量被称为局部变量.变量声明和初始化都是在方法中,方法结束后,变量就会自动 ...
- java中的对象,类。与 方法的重载。
对象: 一切皆为对象.对象包括两部分内容:属性(名词形容词),行为(动词).对象和对象之间是有关系的: 派生,关联,依赖. 类: 对同一类别的众多对象的一种抽象.类,还是用来生成对象的一种模板,对象是 ...
随机推荐
- 格式化p6spy的输出日志
众所周知, p6spy打印出来的日志是一行很长很长的内容, 很不容易查看, 牛B的p6spy为什么就不能想hibernate那样有format_sql的功能? 竟然没有, 我只好自己动手写一个日志输出 ...
- 某题目2 状压DP
Description 对于一个数列,其混乱度定义为连续相等的数的段数.如:1 2 1 2 1,其混乱度为5,而:1 2 2 3 3,其混乱度为3.现给出一个数列,允许取出k个数并允许插入数列中的任意 ...
- css基础 行内元素 块级元素
1.行内元素(内联元素 inlineElement) 特点:不占据一行,无法设置宽高及行高,其宽度随着内容增加,高度随字体大小而改变,margin只对左右起作用,上下无效. 常见有: a - 锚点,b ...
- Codeforces Round #404 (Div. 2) B. Anton and Classes 水题
B. Anton and Classes 题目连接: http://codeforces.com/contest/785/problem/B Description Anton likes to pl ...
- U盘量产大致研究思路
这几天搞了一波U盘量产,很多年前玩的基本都是些皮毛,比如U盘分区,U盘启动,以及台电U盘的光驱启动等等,这些现在看起来其实都不入眼,只是简单的将U盘分个区,并且没玩到主控上面去. 下面是一些自己的理解 ...
- [Winform]安装在C盘,无操作权限的一个解决办法
摘要 在对winform打包,进行安装的时候,一般会采用默认的安装路径,默认安装在C:\Program Files\xx或者C:\Program Files(x86)目录下,但windows有一种安全 ...
- EF+Sqlite 动态设置连接字符串
摘要 在做c/s项目的时候,如果使用ef+sqlite,我们不知道客户端会安装在哪里,需要动态的来设置db所在路径. 解决办法 /// <summary> /// 数据上下文 /// &l ...
- 移植Python3到TQ2440(二)
接着前一篇博文. 在上一篇博文中我们用NFS挂载根文件系统的方式启动了系统,接下来我们把移植了Python3的根文件系统固化到NandFlash中,但是由于linux-4.9目前不支持Yaffs2文件 ...
- struct对象可能分配在托管堆上吗
struct对象可能被分配在托管堆上吗? --会的. 比如当对struct装箱的时候,就会被分配在托管堆上. 比如,让一个struct实现一个接口. public interface IReport ...
- 用xcode 5 开发访问IOS 7上面的通讯录有问题
NSMutableArray *addressBookTemp = [NSMutableArray array]; ABAddressBookRef addressBooks = ABAddressB ...