面向对象的三大特征
封装及其必要性
package com.github.hcsp;
public class Home {
public static void main(String[] args) {
Light light = new Light();
light.turnOn();
Light light2 = new Light();
light2.打开电路1();
light2.打开电路2();
light2.打开电路3();
}
}
package com.github.hcsp;
public class Light {
public void turnOn() {
打开电路1();
打开电路2();
打开电路3();
}
public void 打开电路3() {}
public void 打开电路2() {}
public void 打开电路1() {}
}
人的案例
package com.github.hcsp;
public class Person {
public Integer id;
public String name;
public int age;
}
package com.github.hcsp;
public class Person {
private Integer id;
private String name;
private int age;
public void setId(Integer id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
if (age < 0) {
this.age = 0;
} else if (age > 100) {
this.age = 100;
} else {
this.age = age;
}
}
}
- 总结:1.如果不使用封装,所有属性都用public去暴露就很难去改变
访问控制符
- java有四种访问控制符
- public,所有的人都能访问
- protected,只有子类可以访问和同一个包的才能访问,包可提供封装的边界,
package com.github.hcsp.controlflow.Sub;
import com.github.hcsp.Person;
public class PersonSubClass extends Person {
public PersonSubClass() {
this.id = 1;
}
}
- 包级私有,不加任何访问限定符就是包级私有,同一个包可以看到
- private,只有自己能访问,封装的时候一般都用private
getter、setter方法与JavaBean约定
- javaBean里面getter就是得到一个方法,setter就是设置一个方法,快捷键preference-keymap-搜索generate,默认快捷键control + n
- javabean就是一个有getter和setter的对象,如果有getter和setter就认为这个java bean 存在某个属性,字符串和布尔值的设置方法不同
- 这是最重要的约定
getter: getX 属性
getter: isX 属性
setter: setX 属性
为什么要有javaBean
- json对象和java对象相互转换
- 序列化就是把一个内存对象转换成字节流,字符串等人能看的东西,反序列化就是字符串转成内存的对象
- fastJSON案例
package com.github.hcsp;
import com.alibaba.fastjson.JSON;
public class Cat {
private String name;
private boolean cute;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isCute() {
return cute;
}
public Cat(String name, boolean cute) {
this.name = name;
this.cute = cute;
}
public void setCute(boolean cute) {
this.cute = cute;
}
public static void main(String[] args) {
Cat cat = new Cat("喵", true);
System.out.println(JSON.toJSONString(cat));
String s = "{\"cute\":true,\"name\":\"喵\"}";
cat = JSON.parseObject(s, Cat.class);
System.out.println("cat = " + cat);
}
}
- 结论:在java中转换json,只看getter和setter方法,不看实际的属性。
- javaBean的好处提供了封装,为软件的演进提供了很大的保证
设计模式实战:静态工厂方法
- 推荐书籍effective java,作者 Joshua Bloch,第三版
- 静态工厂方法,最大的优点有名字,清楚告诉自己在做什么,描述自己做什么
- 为什么不写注释,注释不会被编译,如果过时了还不如不写,错误注释的情况比没有注释更糟糕
- 重构的一大原则就是取消注释,写成方法
- 静态工厂方法的第二个好处是不一定要返回对象
- 静态工厂方法的第三个方法是可以返回对象的子类,以提高静态方法的灵活性
- 第四个好处,每次调用返回不同的对象,根据输入的参数去创建不同的对象,不需要创建新的对象,好处是省时间和内存
package com.github.hcsp;
import com.alibaba.fastjson.JSON;
import com.sun.org.apache.xpath.internal.operations.Bool;
public class Cat {
private static final Cat INVALID_CAT = new Cat("Invalid cate", true)
private String name;
private boolean cute;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isCute() {
return cute;
}
public static Cat newCuteCat(String name) {
if (name == null || name.isEmpty()) {
return INVALID_CAT;
} else if (name.contains("white")) {
return new WhiteCat(name, true);
}
return new Cat(name, true);
}
public static class WhiteCat extends Cat {
public WhiteCat(String name, boolean cute) {
super(name, cute);
}
}
public static Cat newUnCuteCat(String name) {
return new Cat(name, false);
}
public Cat(String name, boolean cute) {
this.name = name;
this.cute = cute;
}
public void setCute(boolean cute) {
this.cute = cute;
}
public static void main(String[] args) {
Cat cat = new Cat("", true);
Boolean b = new Boolean(true);
}
}
设计模式实战:静态工厂方法的缺点
- 没有办法去子类化,就是一个普通的方法
- 很难让开发者找到,由于名字重新命名了
- JDK中的很多静态工厂的例子布尔值的 valueOf
- Integer类有相应的parseInt
静态工厂方法创建的原则
类的访问控制符
- 常见的两个public和什么都不加就是高级私有
- public 任何类都可以访问
- final 不是访问限定符
如何强行的去访问一个高级私有的类


Java模块系统简介
- jdk8 最大的访问限制就是包,JDK9可以把多个包当成module导出
- jdk9太新了,2017年出的,
- jdk8没有办法阻止,只能通过约定,比如internal包下的就是不能让外部访问的

builder模式
- 解决属性过多,创建构造器过长的问题
- 要安装插件builderGenerator
- 生成builder
- 使用bulder,builder是非常常用的模式
package com.github.hcsp;
public class Main {
private static Object Person;
public static void main(String[] args) {
Person = PersonBuilder.aPerson()
.withFirstName("")
.withLastName("")
.withAddress("").build();
}
}