Java高效编程系列(一)
平时也是会去看一些书籍的,只是没有太大的意愿整理成文,一是这样确实会有点耽误时间,需要对文章进行排版,测试用例也不能写的太随意,然后组织语言进行分析讲解,二是因为语言表达确实是我的一个弱项,最后一个也是比较重要的一个原因,我确实有点懒🥶。不过为了克服上面的种种困难,我还是要坚持写作,热爱学习,至于内容的话,我准备把最近学习的内容分享出来,内容是来源于Effective Java这本书,接下来的一段时间里,都会分享一些自己的学习内容。
学习的内容
1.使用静态工厂方法代替构造器
按照平时常规的开发习惯,如果我们想要一个对象,可以直接通过new来创建,也就是通过这个类提供的共有构造器来完成,而对于一些特殊场景,我们也可以用下面这种方式:
- 常规写法示例
Test one = new Test();
Test two = new Test(1);
Test three = new Test(1,2);
Test four = new Test(1,2,3);
- 静态工厂方法示例1
//eg2.
Integer param = Integer.valueOf(1);
//eg2 实现代码
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
- 静态工厂方法示例2
//eg2
Stack stack = new Stack();
stack.add(1);
Collections.list(stack.elements());
//eg2 实现代码
public static <T> ArrayList<T> list(Enumeration<T> e) {
ArrayList<T> l = new ArrayList<>();
while (e.hasMoreElements())
l.add(e.nextElement());
return l;
}
- 静态工厂方法示例3
//eg3
Calendar calendar = Calendar.getInstance();
//eg3 实现代码,这里就贴部分代码,可以打开源码自己看下
Calendar cal = null;
if (aLocale.hasExtensions()) {
String caltype = aLocale.getUnicodeLocaleType("ca");
if (caltype != null) {
switch (caltype) {
case "buddhist":
cal = new BuddhistCalendar(zone, aLocale);
break;
case "japanese":
cal = new JapaneseImperialCalendar(zone, aLocale);
break;
case "gregory":
cal = new GregorianCalendar(zone, aLocale);
break;
}
}
}
return cal;
小结:
我觉得使用静态工厂方法的几处优点还是不错的
- 如果一个类的构造器太多,在创建对象的时候就会比较懵,如果按照规范的名称命名静态工厂方法,这样后续代码的可读性是比较高的,比如常见的valueOf、getInstance这种
- 不一定每次调用都创建一个新的对象,也就是可以反复使用对象,比如示例1
- 我们可以对方法内部进行自定义,这样我们可以返回该类型的子类对象,比如示例3
书中给出的建议就是两者各有长处,而静态工厂经常更加合适,所以以后开发可以先考虑静态工厂👍
2.如何使用构建器
今天要分享的另一个知识点,就是使用构建器来创建实例,这种方式适合这种情况:当我们创建一个新的对象时,需要传入很多参数,多的时候甚至是几十上百个,这个时候如果用下面这两种常规写法,我觉得还是蛮累的...
//方式一
Test test = new Test(1,2,3,4,5,6,7,8,9,0);
//方式二
Test test = new Test();
test.setParam1(1);
test.setParam2(2);
test.setParam3(3);
test.setParam4(4);
test.setParam5(5);
test.setParam6(6);
test.setParam7(7);
....
第一种方式的可读性基本为0,如果有更多的参数,使用这种方式,一旦调用时候出现问题,需要去检查参数的时候,看到这种编码方式,我的内心是拒绝的。
第二种方式其实可读性还是可以的,大部分时间我们可能用的就是这种方式,也不会出啥问题的,我们可以先看一下下面这段代码
public class Test {
static Fruit apple = null;
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
apple = new Fruit();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//error info
}
apple.setName("apple");
});
Thread t2 = new Thread(() -> {
System.out.println("apple name:"+apple.getName());
});
t1.start();
Thread.sleep(500);
t2.start();
}
}
@Data
class Fruit{
private String name;
}
这段逻辑我最初是希望线程t1创建好Fruit,并且进行赋值,然后t2线程来获取t1线程创建的对象的name值,这里我是夸张了一点,来模拟实际可能出现t1还没有完成name赋值时,它的CPU时间片就已经用完,CPU就会切换到执行t2逻辑,导致未达到我们的预期。
这种情况下,我们就可以使用构建器来处理,我还是先直接上代码
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
public static class Builder{
//required parameters
private final int servingSize;
private final int servings;
//Optional parameters
private int calories;
private int fat;
public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
}
public Builder calories(int var){
calories = var;
return this;
}
public Builder fat(int var){
fat = var;
return this;
}
public NutritionFacts build(){
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder) {
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
}
}
使用方式 为了让代码更简洁点,参数上就写了两个必填参数(servingSize、servings),两个个性化参数(calories、fat)。首先是在原有类中增加一个静态内部类,内部类用于对所需要的参数进行赋值,当一切赋值完成后,就会调用内部类的build方法来实例化外部类。
NutritionFacts facts = new NutritionFacts.Builder(240,8)
.calories(100).sodium(35).carbohydrate(27)
.build();
使用场景 简单来说,这种方式适合构造器有多个参数,特别是有些参数是必传,而有些又是可选参数的时候,构建器模式无论是后续扩展还是可读性以及安全性上,都是很好用的。
有几点小细节我觉得有必要注意一下:
- 内部类为静态内部类,这句话是废话...
- 内部类的构造器和方法是public
- 赋值每一个参数后,要return this,因为要连续对变量赋值
- 外部类的构造器为private
总结
今天先分享上面几个知识点,对于上面这些知识点,其实小伙伴们看书也是一样的,但是还是建议小伙伴们看完之后可以发出来,和jy们一块讨论讨论,不然只看书容易犯困,分享出来可以让记忆更加深刻,还能学习一些额外的知识点,当然也避免不了被喷,这也是加深记忆的一种方式。
写在最后
最后,我想说,给我推荐到首页吧,我想要那俩陶瓷碗😂。
转载自:https://juejin.cn/post/7243780412547858488